В этой небольшой заметке мы поговорим о том, как парсить флаги и аргументы командной строки в языке Go . Казалось бы, в стандартной библиотеке есть пакет flag — берешь и используешь. Но он плох тем, что заставляет пользователя указывать флаги в стиле -config
, вместо всем привычных -c
и --config
. То есть, когда два знака минус используются для полного имени флага, и один знак для короткого. Кроме того, pflag не помогает обрабатывать сложные команды вроде тех, что использует утилита kubectl — get nodes
, describe pods
, и так далее.
Поэтому вместо стандартного flag многие используют spf13/pflag :
import (
log «github.com/sirupsen/logrus»
«github.com/spf13/pflag»
)
func main () {
var showHelp bool
var configPath string
pflag . StringVarP ( &configPath , «config» , «c» , «» ,
«Config file path» )
pflag . BoolVarP ( & showHelp , «help» , «h» , false ,
«Show help message» )
pflag . Parse ()
if showHelp {
pflag . Usage ()
return
}
log . Infof ( «configPath == %s» , configPath )
}
Библиотека предельно проста в использовании, поэтому не будем подробно на ней останавливаться. Стоит только отметить, что в ней нет понятия «обязательного аргумента». Дело в том, что библиотека работает с флагами, а все флаги по определению опциональны. Зато в spf13/pflag есть проверка множества разных форматов . Например, можно убедиться, что пользователь указал правильный IP-адрес, и всякое в таком духе.
Аргументы часто парсятся с помощью spf13/cobra . Cobra позиционируется как фреймворк для написания CLI с интерфейсом в стиле kubectl get pods
. Пример использования:
import (
log «github.com/sirupsen/logrus»
«github.com/spf13/cobra»
)
func main () {
var configPath string
rootCmd := cobra . Command {
Use : «rest-service-example» ,
Version : «v1.0» ,
Run : func ( cmd * cobra . Command , args [] string ) {
log . Infof ( «configPath == %s» , configPath )
},
}
rootCmd . Flags () . StringVarP ( & configPath , «config» , «c» , «» ,
«Config file path» )
err := rootCmd . MarkFlagRequired ( «config» )
if err != nil {
panic ( «rootCmd.MarkFlagRequired() failed» )
}
err = rootCmd . Execute ()
if err != nil {
// Required arguments are missing, etc
return
}
}
Заметьте, что флаг --config
теперь стал обязательным.
Больше примеров вы найдете в документации . Например, из нее вы узнаете, как сделать поддержку нескольких команд в одной утилите и построить из этих команд иерархию. А еще, что cobra имеет безумный функционал типа генерации автокомплишена для Bash и Zsh .
Интересно, что kubectl
реально написан с использованием данных библиотек.
А чем вы парсите флаги и аргументы в Go?
Дополнение: Парсинг конфигов в Go с помощью Viper