ただの技術メモ

個人備忘録

flag packageのflag.IntVarとflag.Intの違いとflag.Parse()を呼び出す必要性

何が違ってどういう使い分けするんだっけといつも調べている気がするのでメモしておきます。

flag packageには以下のような2つの使い方があります。

① 返り値付きの関数でフラグを取得する(ポインタが返ってきます)

var nFlag = flag.Int("n", 1234, "help message for flag n")

②変数にバインドする形でフラグを取得する

var flagvar int
func init() {
    flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}

まあ使い方の違いは良いとして、どういう使い分けをするんだと毎回思います。

ドキュメントのexampleを見てみると、どうやら1つの変数を複数のフラグで共有したいときなどに②が便利なようです。

// Example 2: Two flags sharing a variable, so we can have a shorthand.
// The order of initialization is undefined, so make sure both use the
// same default value. They must be set up with an init function.
var gopherType string

func init() {
    const (
        defaultGopher = "pocket"
        usage         = "the variety of gopher"
    )
    flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
    flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)")
}

あと、flag.Parse()は何のために必要なんだっけと毎回忘れてしまいます。

そもそもflag.Intflag.IntVarの段階では初期値を与えているだけで、コマンドライン引数のフラグは解析されていないようです。

そのコマンドライン引数のフラグを解析して、変数に格納するのがflag.Parse()です。

以下のようなコードで検証してみると分かると思います。

package main

import (
    "flag"
    "fmt"
)

var addr = flag.String("addr", ":80", "tcp host:port to connect")

func main() {
    fmt.Println(*addr)
    flag.Parse()
    fmt.Println(*addr)
}

ドキュメントは以下です。

pkg.go.dev