Skip to content

Пакет flag в Go: FlagSet для реализации субкоманд

В современных приложениях командной строки часто реализуются субкоманды, что позволяет объединить набор инструментов в одной команде. Самый известный инструмент, использующий такую схему, называется git. При проверке такой команды как git init, командой является git, а init является субкомандой git. Важная характеристика субкоманд заключается в том, что каждая субкоманда может иметь собственный набор флагов.

Приложения Go могут поддерживать субкоманды с собственным набором флагов, используя оператор типа flag.( *FlagSet). Для иллюстрации мы создадим программу, которая будет реализовать команду, используя две субкоманды с разными флагами.

Создай новый файл с именем subcommand.go и добавь в него следующий код.

Эта программа разделена на несколько частей: функция main, функция root и отдельные функции для реализации субкоманды.

Функция main обрабатывает ошибки, возвращаемые командами. Если любая функция возвращает ошибку, выражение if определит ее, распечатает ошибку и закроет программу с кодом состояния 1, сообщающим операционной системе о возникновении ошибки. Внутри функции main мы передаем все аргументы вызова программы в функцию root. Удалим первый аргумент, представляющий собой имя программы (в предыдущих примерах ./subcommand), выделив срез os.Args.

Функция root определяет []Runner, где определяются все субкоманды. Runner — это интерфейс субкоманд, позволяющий функции root получить имя субкоманды с помощью Name() и сравнить его с содержанием переменной subcommand. После обнаружения правильной субкоманды посредством итерации переменной cmds мы инициализируем субкоманду с остальными аргументами и вызываем метод Run() для этой команды.

Мы определяем только одну субкоманду, хотя эта структура позволяет легко создавать и другие команды. Экземпляр GreetCommand создается с помощью NewGreetCommand при создании нового *flag.FlagSet с помощью flag.NewFlagSet.

flag.NewFlagSet принимает два аргумента: имя набора флагов и стратегию отчета об ошибках проверки синтаксиса. Имя *flag.FlagSet доступно с помощью flag.( *FlagSet).

Метод Name мы используем в (*GreetCommand).Name() так, что имя субкоманды соответствует имени, которое мы присвоили *flag.FlagSet. NewGreetCommand также определяет флаг -name аналогично предыдущим примерам, но вместо этого вызывает его как метод поля *flag.FlagSet *GreetCommand, gc.fs. Когда функция root вызывает метод Init() команды *GreetCommand, мы передаем указанные аргументы методу Parse поля *flag.FlagSet.

Субкоманды будет проще увидеть, если ты соберешь эту программу и запустишь ее. Выполни сборку программы.

Теперь запусти программу без аргументов.

Ты увидишь следующий результат: You must pass a sub-command.

Теперь запусти команду с субкомандой greet.

Результат будет выглядеть следующим образом: Hello World ! 

Теперь используй флаг -name с greet для указания имени.

Программа выведет следующее: Hello Sammy ! 

В этом примере проиллюстрированы некоторые принципы структурирования больших приложений командной строки в Go. Наборы FlagSet разработаны так, чтобы дать разработчикам больше контроля над местом и способом обработки флагов логикой синтаксической проверки флагов.

Флаги делают приложения более полезными в разных условиях, поскольку они дают пользователям контроль над способом выполнения программы. Очень важно предоставить пользователям полезные параметры по умолчанию, но также следует дать им возможности изменять параметры, которые не подходят для их конкретной ситуации. Ты увидел, что пакет flag предоставляет пользователям гибкие возможности выбора конфигурации. Ты можешь выбрать несколько простых флагов или создать разветвленный набор субкоманд. В любом случае, использование пакета flag поможет выполнить сборку утилит в стиле длинной истории гибких инструментов командной строки с поддержкой сценариев.

Со основным источником ты можешь ознакомиться по ссылке.

Рекомендуем также ознакомиться с дополнительными материалами: