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

时间:2015-08-03 11:36:16

标签: go command-line-interface command-line-arguments

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

7 个答案:

答案 0 :(得分:22)

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

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

答案 1 :(得分:6)

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

var opts struct {
...
    // Example of a required flag
    Name string `short:"n" long:"name" description:"A name" required:"true"`
...
}

答案 2 :(得分:5)

作为already mentionedList<ApplicationInfo> packages; PackageManager pm; pm = getPackageManager(); //get a list of installed apps. packages = pm.getInstalledApplications(0); ActivityManager mActivityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); for (ApplicationInfo packageInfo : packages) { if((packageInfo.flags & ApplicationInfo.FLAG_SYSTEM)==1)continue; if(packageInfo.packageName.equals("mypackage")) continue; mActivityManager.killBackgroundProcesses(packageInfo.packageName); } 包不直接提供此功能,通常您可以(并且应该)能够提供合理的默认值。对于只需要少量显式参数(例如输入和输出文件名)的情况,您可以使用位置参数(例如,在flag之后检查flag.Parse()然后flag.NArg()==2)。< / p>

但是,如果你认为这是不明智的;说一些你想以任何顺序接受的整数标志,其中任何整数值是合理的,但没有默认值。然后,您可以使用flag.Visit函数检查您关注的标记是否已明确设置。我认为这是判断标志是否显式设置为默认值的唯一方法(不计算具有保持状态的input, output := flag.Arg(0), flag.Arg(1)实现的自定义flag.Value类型。)

例如,可能是:

Set

Playground

如果未明确设置“-b”或“-s”标志,则会产生错误。

答案 3 :(得分:5)

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)

答案 4 :(得分:3)

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

mmap

答案 5 :(得分:2)

我同意this solution,但就我而言,默认值通常是环境值。例如,

dsn := flag.String("dsn", os.Getenv("MYSQL_DSN"), "data source name")

在这种情况下,我想检查值是通过调用(通常是本地开发)还是环境var(产品环境)设置的。

因此,进行一些小的修改,就可以满足我的情况了。

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

Test example in plauground

答案 6 :(得分:0)

或者您也可以docopt,而您只需要编写“用法”文本即可。 Docopt解释用法文本并创建参数映射。遵循POSIX使用文本标准,这提供了很多可能性。该库已经支持大约20种语言。

https://github.com/docopt/docopt.go

package main

import (
        "fmt"
        "github.com/docopt/docopt-go"
)

const (
        Usage = `Naval Fate.

Usage:
  naval_fate ship new <name>...
  naval_fate ship <name> move <x> <y> [--speed=<kn>]
  naval_fate ship shoot <x> <y>
  naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate -h | --help
  naval_fate --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.`
)

func main() {
        args, _ := docopt.ParseDoc(Usage)
        fmt.Println(args)
}