【发布时间】:2019-06-28 04:10:08
【问题描述】:
我正在使用 go 的原生 "flag" 包。
它内置了访问所有当前定义的标志的能力,使用flag.VisitAll。
我正在尝试构建一个 sn-p 来尝试从环境变量中获取该标志的值(如果存在)并且在未设置标志的情况下,我无法找到一种方法来确定是否是否设置了特定标志。
有什么方法可以在不实现新参数类型的情况下实现这一点?
【问题讨论】:
标签: go
我正在使用 go 的原生 "flag" 包。
它内置了访问所有当前定义的标志的能力,使用flag.VisitAll。
我正在尝试构建一个 sn-p 来尝试从环境变量中获取该标志的值(如果存在)并且在未设置标志的情况下,我无法找到一种方法来确定是否是否设置了特定标志。
有什么方法可以在不实现新参数类型的情况下实现这一点?
【问题讨论】:
标签: go
使用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)
}
【讨论】: