В този урок обсъждаме как да кодираме помощно съобщение с помощта на пакета Cobra.
› Накратко за Cobra
Cobra е мощен пакет от команден ред за Golang. Пълният списък на проектите, които използват Cobra, е тук.
> Преди да започнеш
Инсталирайте Cobra във вашата машина:
go get -u -v github.com/spf13/cobra
И все пак не е необходимо да създавате файлове на нашето приложение. Има „генератор“, който помага много лесно да създадете работеща директория.
За да инсталирате генератора, използвайте тази команда:
go get -u -v github.com/spf13/cobra/cobra
Преди да започнем да кодираме, нека прегледаме помощно съобщение, което ще създадем с пакета Cobra.
› Писане на помощно съобщение
Помощно съобщение (или съобщение за използване, илидокумент) е това, което потребителите виждат, когато
- извикване на програма,
- въведете флаг като
--h
или-h
, - въведете невалидни аргументи.
Това съобщение включва името на програмата, нейното използване и опции. Ако използвате командния ред, вече сте запознати с помощните съобщения или съобщенията за използване. В Linux обикновено можете да въведете program --help
, за да получите списък с приемливи аргументи на програмата.
В този урок пишем помощно съобщение за програма, която извежда:
- списък от произволни числа с определен брой и диапазон, или
- списък с произволни букви от конкретен брой и език.
Това е нашето съобщение за употреба:
Нека анализираме команда, числа, от предходното съобщение:
randx numbers --count <count> [--range <range>...]
randx
— име на програмата,numbers
— команда,--count
— опция на командата,<count>
— стойност на опцията — брой,[--range <range>…]
— незадължителен параметър, който изисква стойност или няколко стойности,[--verbose]
— незадължителен флаг.
Имаме две команди, numbers
и letters
(bool), за да активираме съответно режима с цифри или букви. Ако едно от тях е вярно, друго е невярно.
Опцията — count
(int) е необходима и за двете команди numbers
и letters
. Програмата извежда списък с цифри или букви от посочения брой.
$ randx numbers --count 1
$ randx letters --count 1
За да декларираме незадължителен аргумент --range
([]низ),използваме квадратни скоби. Три точки в квадратните скоби означават, че можете да подадете няколко аргумента към командния ред. Например,
--range 1,10 --range 1,11
or
--range 1-10 --range 1-11
or
--range 1:10 --range 1:11
Тази опция задава диапазон от произволни числа. Ако има два аргумента, програмата извежда два списъка с посочените диапазони.
Незадължителният аргумент, --lang
(низ), също е в квадратни скоби. Опциятаприема език. Следователно програмата извежда букви на посочения език.
Програмата трябва да върне помощно съобщение, когато необходимата опция не е зададена и/или аргументите са невалидни. И двете опции--range
и --lang
могат да бъдат пропуснати.
Освен това имаме три опции (или само флагове) без операнди в съобщението за използване:
-h / --help
— изведе съобщението за използване,--verbose
—изведе подробности за това какво прави програмата; флагът се използва за информиране на потребителя какво всъщност прави програмата, включително грешки при извършване на необходимо действие. Това може да бъде полезно за отстраняване на проблеми.--version
— изведе версията на програмата, която използвате.
› Генериране на структура на проекта
- Създайте и отидете в директория:
mkdir -p ~/go/src/github.com/your_username/app && cd ~/go/src/github.com/your_username/app
2. Генерирайте структура на проект с cobra init
:
cobra init --pkg-name ~/go/src/github.com/your_username/app
След това имаме следната структура на проекта:
— — cmd — — — root.go — — LICENSE — — main.go
Файлът root.go съдържа rootCmd
command, който инициализира всички команди и флагове (или опции).
› Създаване на команди
За да добавите нова команда, просто използвайте cobra add commandName
в директорията на проекта. За нашето помощно съобщение трябва да създадем две команди numbers
и letters
:
$ cobra add numbers $ cobra add letters
След това пакетът cobra генерира два файла, а именно numbers.go и letters.go в директорията cmd. Сега имаме следната структура на проекта:
— — cmd — — — root.go — — — numbers.go — — — letters.go — — LICENSE — — main.go
› Как изглежда main.go
Във файлаmain.go ние изпълняваме нашите команди с cmd.Execute()
. Пълният код изглежда така:
package main import “github.com/your_user_name/app/cmd” func main() { cmd.Execute() }
Тук не е необходимо да добавяте допълнителен код. Нека създадем подкоманди и опции във файловете numbers.go и letters.go.
› Команда за числа
Cobra генерира част от следния код. Декларирахме променливи countFlagNumbers
и rangeFlagNumbers
за съхраняване на стойности съответно от --count
и --range
флагове. Освен това инициализирахме необходимите флагове (--count
и --range
) във функцията init()
.
// beginning of numbers.go package cmd import ( "fmt" "github.com/spf13/cobra" ) var ( countFlagNumbers int rangeFlagNumbers []string ) var numbersCmd = &cobra.Command{ Use: "numbers", Short: "Returns random numbers", Run: func(cmd *cobra.Command, args []string) { fmt.Println("numbers mode") fmt.Println("--count:", countFlagNumbers) fmt.Println("--range:", rangeFlagNumbers) fmt.Println("--verbose:", verbose) }, } // here is init()
Извикваме arootCmd.AddCommand()
метод, за да инициализираме командата numbers
.
//beginning of init() func init() { rootCmd.AddCommand(numbersCmd) ...
Декларацията на всеки флаг има следния модел:
commandName.Flags().TypeOfValuesP( where to store, long flag name, short flag name, default value, explanation, )
Декларирайте флага --count
:
... numbersCmd.Flags().IntVarP( &countFlag, "count", "c", 0, "A count of random numbers", ) ...
И направете този флаг задължителен:
... numbersCmd.MarkFlagRequired("count") ...
Когато направим флаг задължителен, това означава, че потребителят не може да изпълни програмата без този флаг. Ще има грешка.
Декларирайте флага --range
:
... numbersCmd.Flags().StringSliceVarP( &rangeFlag, "range", "r", []string{"1:100"}, "Range of numbers. Optional", ) } // end of init() // end of numbers.go
› Команда букви
Същото като в numbers.go, беше генериран част от следния код. Тук декларирахме променливи countFlagLetters
и langFlagLetters
за съхраняване на получените стойности съответно от флаговете --count
и --lang
.
// beginning of letters.go package cmd import ( “fmt” “github.com/spf13/cobra” ) var ( countFlagLetters int langFlagLetters string )
Командата lettersCmd
има същата структура като numbersCmd
. Всички флагове се инициализират по същия начин, както във файла numbers.go.
var lettersCmd = &cobra.Command{ Use: "letters", Short: "Returns random letters", Run: func(cmd *cobra.Command, args []string) { fmt.Println("letters mode") fmt.Println("--count:", countFlagLetters) fmt.Println("--lang:", langFlagLetters) fmt.Println("--verbose:", verbose) }, } func init() { rootCmd.AddCommand(lettersCmd) lettersCmd.Flags().IntVarP( &Count, "count", "c", 0, "A count of random letters", ) lettersCmd.MarkFlagRequired("count") lettersCmd.Flags().StringVarP( &Lang, "lang", "l", "en", "A language. Optional", ) } // end of letters.go
› Добавяне на флагове Version и Verbose
В root.go актуализираме използването на нашата програма, добавяме флаговете --version
и
_52.
package cmd import ( "fmt" "os" "github.com/spf13/cobra" )
Декларирайте подробна променлива. Има тип bool.
var ( verbose bool )
За да се покаже версията на нашата програма, добавете Version
параметър и посочете текущата версия в кавички.
var rootCmd = &cobra.Command{ Use: "randx", Version: "1.0.1", Short: "Returns random numbers or letters.", } func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } }
Флагът--verbose
е постоянен и глобален. Което означава, че можете да кажете на програмата да ви покаже подробности за изпълнението на програмата с всяка команда и зададен флаг.
func init() { rootCmd.PersistentFlags().BoolVarP( &verbose, "verbose", "v", false, "Verbose output", ) }
› Използване
В този раздел можете да намерите няколко случая как да използвате Cobra в командния ред.
›› Режим на букви
$ go run main.go letters --count 9 $ go run main.go letters -c 9 letters mode --count: 9 --lang: en // this is a default value --verbose: false $ go run main.go letters --count 9 --lang en $ go run main.go letters -c 9 -l en letters mode --count: 9 --lang: en --verbose: false
›› Режим на числа
$ go run main.go numbers --count 9 $ go run main.go numbers -c 9 numbers mode --count: 9 --range: [1:100] // this is a default value --verbose: false $ go run main.go numbers --count 10 --range 9,10 $ go run main.go numbers -c 10 -r 9,10 numbers mode --count: 10 --range: [9 10] --verbose: false $ go run main.go numbers --count 10 --range 9,10 --range 0,15 numbers: true --count: 10 --range: [9 10 0 15] --verbose: false
Някои коментари относно разделителите. Ако използвате запетаята като разделител в--range
флаг, ще получите само списък с числа. Както беше обсъдено по-рано, можете да използвате colon:
, за да разделите тези числа. Например:
$ go run main.go numbers --count 10 --range 9:10 --range 10:11 numbers mode --count: 10 --range: [9:10 10:11] --verbose: false
›› Многословно
$ go run main.go numbers --count 18 --range 9,19 --verbose $ go run main.go numbers -c 18 -r 9,19 --verbose numbers mode --count: 18 --range: [9 19] --verbose: true
› За автора
Джейн е програмист на Go и технически писател в софтуерното инженерство. Тя пише технически материали от 5 години на английски и руски език. Завършила е специалност „Информационна сигурност“ в Новосибирския държавен технически университет и специализира информационна сигурност на автоматизирани системи. Можете да я последвате в Twitter и да видите другите й писмени работи на publications.enthusiastic.io.