有没有办法确定使用`flag.VisitAll`时是否设置了标志?

问题描述 投票:0回答:3

我正在使用 go 的原生

"flag"
包。

它内置了使用

flag.VisitAll
访问所有当前定义的标志的能力。

我正在尝试构建一个片段,尝试从环境变量中获取该标志的值(如果存在)并且如果未设置该标志,并且我找不到一种方法来确定特定标志是否已设置设置或不设置。

有没有办法在不实现新参数类型的情况下实现这一点?

go
3个回答
2
投票

使用

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


1
投票

没有函数可以遍历未设置的命令行标志。但是,可以通过获取

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

0
投票

使用 https://github.com/cardinalby/go-struct-flags/ 您可以定义指针字段,如果未提供标志,则保留

nil

另一种方法是定义您自己的

flag.Value
,但这会阻止默认
Usage
打印标志类型和默认值。

使用

Visit
也是可以的,但不是很方便。

© www.soinside.com 2019 - 2024. All rights reserved.