可以将Go中的命令行标志设置为强制标志吗?

Pet*_*lák 36 command-line-interface go command-line-arguments

有没有办法设置某些标志是强制性的,还是我必须自己检查它们的存在?

icz*_*cza 26

flag包不支持强制或必需的标志(意味着必须明确指定标志).

你可以做的是为(所有)标志使用合理的默认值.如果某个标志类似于没有合理的默认值,请检查应用程序开头的值并停止并显示错误消息.你应该进行标志值验证(不仅仅是对于必需的标志),所以这不应该意味着任何(大的)开销,这是一般的好习惯.


Dav*_*e C 8

正如已经提到的,该flag包不直接提供这个功能,通常你可以(也应该)能够提供一个合理的默认。如果您只需要少量的显式参数(例如,输入和输出文件名),则可以使用位置参数(例如,flag.Parse()先检查flag.NArg()==2后再选择input, output := flag.Arg(0), flag.Arg(1))。

但是,如果您遇到这种情况并不明智;说出您要以任何顺序接受的一些整数标志,其中任何整数值都是合理的,但没有默认值。然后,您可以使用该flag.Visit功能来检查您关心的标志是否已显式设置。我认为这是判断标志是否明确设置为其默认值的唯一方法(不flag.Value使用Set保留状态的实现来计算自定义类型)。

例如,也许类似:

    required := []string{"b", "s"}
    flag.Parse()

    seen := make(map[string]bool)
    flag.Visit(func(f *flag.Flag) { seen[f.Name] = true })
    for _, req := range required {
        if !seen[req] {
            // or possibly use `log.Fatalf` instead of:
            fmt.Fprintf(os.Stderr, "missing required -%s argument/flag\n", req)
            os.Exit(2) // the same exit code flag.Parse uses
        }
    }
Run Code Online (Sandbox Code Playgroud)

Playground

如果未显式设置“ -b”或“ -s”标志,则将产生错误。


Ron*_*Dev 7

我喜欢github.com/jessevdk/go-flags在CLI中使用的包.它是提供required属性,设置标志为必需.像那样:

var opts struct {
...
    // Example of a required flag
    Name string `short:"n" long:"name" description:"A name" required:"true"`
...
}
Run Code Online (Sandbox Code Playgroud)


iKa*_*nor 7

go-flags 允许您声明所需的标志和必需的位置参数:

var opts struct {
    Flag string `short:"f" required:"true" name:"a flag"`
    Args struct {
        First   string `positional-arg-name:"first arg"`
        Sencond string `positional-arg-name:"second arg"`
    } `positional-args:"true" required:"2"`
}
args, err := flags.Parse(&opts)
Run Code Online (Sandbox Code Playgroud)


iva*_*n73 7

如果您有标志路径,只需检查 *path 是否包含某些值

var path = flag.String("f", "", "/path/to/access.log")
flag.Parse()
if *path == "" {
    usage()
    os.Exit(1)
}
Run Code Online (Sandbox Code Playgroud)

  • 可以使用“flag.Usage()”代替“usage()”。 (2认同)

小智 6

我同意这个解决方案,但就我而言,默认值通常是环境值。例如,

dsn := flag.String("dsn", os.Getenv("MYSQL_DSN"), "data source name")
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我想检查这些值是否是从调用(通常是本地开发)或环境变量(产品环境)中设置的。

因此,经过一些小的修改,它适用于我的情况。

使用flag.VisitAll检查所有标志的值。

required := []string{"b", "s"}
flag.Parse()

seen := make(map[string]bool)
flag.VisitAll(func(f *flag.Flag) {
    if f.Value.String() != "" {
        seen[f.Name] = true
    }
})
for _, req := range required {
    if !seen[req] {
        // or possibly use `log.Fatalf` instead of:
        fmt.Fprintf(os.Stderr, "missing required -%s argument/flag\n", req)
        os.Exit(2) // the same exit code flag.Parse uses
    }
}
Run Code Online (Sandbox Code Playgroud)

Test example in plauground