我正在使用 go 的原生
"flag"
包。
flag.VisitAll
访问所有当前定义的标志的能力。
我正在尝试构建一个片段,尝试从环境变量中获取该标志的值(如果存在)并且如果未设置该标志,并且我找不到一种方法来确定特定标志是否已设置设置或不设置。
有没有办法在不实现新参数类型的情况下实现这一点?
使用
flag.VisitAll
听起来有点复杂;我建议使用合理的默认值获取环境变量并将其用作标志的默认值 - 这意味着如果未设置标志,环境变量将是后备:
package main
import (
"flag"
"fmt"
"os"
)
func GetEnvDefault(key, def string) string {
v := os.Getenv(key)
if v == "" {
return def
}
return v
}
func main() {
// Uncomment to test behaviour
// os.Setenv("SERVER_NAME", "donaldduck")
var serverName string
flag.StringVar(&serverName, "n", GetEnvDefault("SERVER_NAME", "mickeymouse"), "The human name for the server")
flag.Parse()
fmt.Println(serverName)
}
VisitAll
和 Visit
返回的标志之间的差异来实现此功能;前者走过所有旗帜,而后者走过设定的旗帜:
func UnsetFlags(fs *flag.FlagSet) []*flag.Flag {
var unset []*flag.Flag
fs.VisitAll(func(f *flag.Flag) {
unset = append(unset, f)
})
fs.Visit(func(f *flag.Flag) {
for i, h := range unset {
if f == h {
unset = append(unset[:i], unset[i+1:]...)
}
}
})
return unset
}
您可以在
flag.Parse
调用之后使用该函数将任何未设置的标志设置为其环境值:
for _, f := range UnsetFlags(flag.CommandLine) {
v := os.Getenv(f.Name)
f.Value.Set(v)
}
使用 https://github.com/cardinalby/go-struct-flags/ 您可以定义指针字段,如果未提供标志,则保留
nil
另一种方法是定义您自己的
flag.Value
,但这会阻止默认 Usage
打印标志类型和默认值。
使用
Visit
也是可以的,但不是很方便。