← На главную

Парсинг флагов и аргументов в языке Go

В этой небольшой заметке мы поговорим о том, как парсить флаги и аргументы командной строки в языке Go. Казалось бы, в стандартной библиотеке есть пакет flag – берешь и используешь. Но он плох тем, что заставляет пользователя указывать флаги в стиле -config, вместо всем привычных -c и --config. То есть, когда два знака минус используются для полного имени флага, и один знак для короткого. Кроме того, pflag не помогает обрабатывать сложные команды вроде тех, что использует утилита kubectl – get nodes, describe pods, и так далее.

Поэтому вместо стандартного flag многие используют spf13/pflag:

package main 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. Пример использования:

package main 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