hfSic

hfSic

flag罠

背景#

flag.Boolおよびflag.BoolVarには奇妙な問題が発生します。

デフォルト値を true に設定すると、

// flag.BoolVar
func main() {
	var getBool bool
	flag.BoolVar(&getBool, "get", true, "booleanを取得")
	flag.Parse()
	fmt.Println(getBool)
}
# 結果
go run main.go -get false
true
// flag.Bool
func main() {
	var getBool *bool
	getBool = flag.Bool("get", true, "booleanを取得")
	flag.Parse()
	fmt.Println(*getBool)
}
# 結果
go run main.go -get false
true

しかし、デフォルト値を false に設定し、コマンドライン引数を true にすると、コードの結果は正常になります(結果が一致するため、一方のみを表示します)。

func main() {
	var getBool *bool
	getBool = flag.Bool("get", false, "booleanを取得")
	flag.Parse()
	fmt.Println(*getBool)
}
# 結果
go run main.go -get true
true

なぜ#

では、コードのコメントを見てみましょう。

// src/flag/flag.go
// Flagはフラグの状態を表します。
type Flag struct {
	Name     string // コマンドラインに表示される名前
	Usage    string // ヘルプメッセージ
	Value    Value  // 設定された値
	DefValue string // デフォルト値(テキストとして);使用メッセージ用
}

// Valueはフラグに格納された動的値へのインターフェースです。
// (デフォルト値は文字列として表されます。)
//
// ValueがIsBoolFlag() boolメソッドを持ち、trueを返す場合、
// コマンドラインパーサーは-nameを-name=trueと等価にします
// 次のコマンドライン引数を使用するのではなく。
//
// Setは、各フラグが存在するコマンドライン順序で一度呼び出されます。
// flagパッケージは、ゼロ値のレシーバーを持つ[String]メソッドを呼び出すことがあります。
// たとえば、nilポインタなど。
type Value interface {
	String() string
	Set(string) error
}

bool フラグ -name はパーサーによって - name=true として解析され、次の引数は解析されません。

# 以下のように -b の後の false は解析されません
# 以下のコマンドは go run main.go -b=true と同等です
go run main.go -b false

どう解決するか#

-name=false-name false の代わりに使用します。

# 結果
go run main.go -get=true -come=false -num 1
true
false
1
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。