【问题标题】:Is there a way to determine whether a flag was set when using `flag.VisitAll`?有没有办法确定使用 `flag.VisitAll` 时是否设置了标志?
【发布时间】:2019-06-28 04:10:08
【问题描述】:

我正在使用 go 的原生 "flag" 包。

它内置了访问所有当前定义的标志的能力,使用flag.VisitAll

我正在尝试构建一个 sn-p 来尝试从环境变量中获取该标志的值(如果存在)并且在未设置标志的情况下,我无法找到一种方法来确定是否是否设置了特定标志。

有什么方法可以在不实现新参数类型的情况下实现这一点?

【问题讨论】:

    标签: go


    【解决方案1】:

    使用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)
    }
    

    见:https://play.golang.org/p/ixDsXH31cBF

    【讨论】:

    • 很好的解决方案,但是,我想回答我最初的问题,即是否可以在不与默认值比较的情况下确定是否设置了标志。
    【解决方案2】:

    没有功能可以遍历未设置的命令行标志。但是,可以通过获取VisitAllVisit 返回的标志之间的差异来实现此功能;前者遍历所有标志,而后者遍历设置标志:

    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)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-19
      • 1970-01-01
      • 2020-06-08
      • 2011-12-06
      • 2011-05-29
      • 1970-01-01
      • 2010-11-19
      相关资源
      最近更新 更多