Могут ли флаги командной строки в Go быть обязательными?
Есть ли способ установить, что определенные флаги являются обязательными, или мне нужно проверить их присутствие самостоятельно?
Ответы
Ответ 1
Пакет flag
не поддерживает обязательные или обязательные флаги (это означает, что флаг должен быть указан явно).
Вы можете использовать разумные значения по умолчанию для (всех) флагов. И если флаг - это что-то вроде разумного значения по умолчанию, проверьте значение в начале вашего приложения и остановите сообщение об ошибке. В любом случае вы должны выполнить проверку значения флага (а не только для обязательных флагов), поэтому это не должно означать каких-либо (больших) накладных расходов, и это хорошая практика в целом.
Ответ 2
Мне нравится пакет 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"'
...
}
Ответ 3
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
Как уже упоминалось, пакет flag
не предоставляет эту функцию напрямую, и обычно вы можете (и должны) быть в состоянии обеспечить разумное значение по умолчанию. Для случаев, когда вам нужно только небольшое количество явных аргументов (например, имя входного и выходного файлов), вы можете использовать позиционные аргументы (например, после flag.Parse()
проверьте, что flag.NArg()==2
и затем flag.NArg()==2
input, output := flag.Arg(0), flag.Arg(1)
).
Если, однако, у вас есть случай, когда это неразумно; скажем, несколько целых флагов, которые вы хотите принять в любом порядке, где любое целочисленное значение является разумным, но по умолчанию нет. Затем вы можете использовать функцию flag.Visit
чтобы проверить, явно ли установлены флаги, которые вам 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
}
}
Playground
Это приведет к ошибке, если либо флаг "-b", либо "-s" не был явно установлен.
Ответ 5
Если у вас есть путь к флагом, просто проверьте, содержит ли * путь какое-то значение
var path = flag.String("f", "", "/path/to/access.log")
flag.Parse()
if *path == "" {
usage()
os.Exit(1)
}