pflag — это замена пакета флагов Go, реализующая --flags в стиле POSIX/GNU.
pflag совместим с расширениями GNU рекомендаций POSIX для параметров командной строки. Более точное описание см. в разделе «Синтаксис флагов командной строки» ниже.
pflag доступен по той же лицензии BSD, что и язык Go, которую можно найти в файле LICENSE.
pflag доступен с помощью стандартной команды go get
.
Установите, запустив:
go get github.com/spf13/pflag
Запустите тесты, запустив:
go test github.com/spf13/pflag
pflag — это замена собственного пакета флагов Go. Если вы импортируете pflag под именем «flag», весь код должен продолжать работать без изменений.
import flag "github.com/spf13/pflag"
Из этого правила есть одно исключение: если вы напрямую создаете экземпляр структуры Flag, вам нужно будет установить еще одно поле «Сокращение». Большая часть кода никогда не создает экземпляр этой структуры напрямую, а вместо этого использует такие функции, как String(), BoolVar() и Var(), и поэтому на нее это не влияет.
Определите флаги, используя flag.String(), Bool(), Int() и т. д.
Здесь объявляется целочисленный флаг -flagname, хранящийся в указателе ip, с типом *int.
var ip * int = flag . Int ( "flagname" , 1234 , "help message for flagname" )
Если хотите, вы можете привязать флаг к переменной, используя функции Var().
var flagvar int
func init () {
flag . IntVar ( & flagvar , "flagname" , 1234 , "help message for flagname" )
}
Или вы можете создать собственные флаги, соответствующие интерфейсу Value (с приемниками указателей), и связать их с анализом флагов с помощью
flag . Var ( & flagVal , "name" , "help message for flagname" )
Для таких флагов значение по умолчанию — это просто начальное значение переменной.
После того, как все флаги определены, вызовите
flag . Parse ()
для анализа командной строки на определенные флаги.
Затем флаги можно использовать напрямую. Если вы используете сами флаги, все они являются указателями; если вы привязываетесь к переменным, они являются значениями.
fmt . Println ( "ip has value " , * ip )
fmt . Println ( "flagvar has value " , flagvar )
Существуют вспомогательные функции для получения значения, хранящегося во флаге, если у вас есть FlagSet, но вам трудно успевать за всеми указателями в вашем коде. Если у вас есть pflag.FlagSet с флагом flagname типа int, вы можете использовать GetInt() для получения значения int. Но обратите внимание, что «флаг» должен существовать и иметь значение int. GetString("flagname") завершится неудачно.
i , err := flagset . GetInt ( "flagname" )
После анализа аргументы после флага доступны как срез flag.Args() или индивидуально как flag.Arg(i). Аргументы индексируются от 0 до flag.NArg()-1.
Пакет pflag также определяет некоторые новые функции, отсутствующие в flag, которые дают однобуквенные сокращения для флагов. Вы можете использовать их, добавив букву «P» к имени любой функции, определяющей флаг.
var ip = flag . IntP ( "flagname" , "f" , 1234 , "help message" )
var flagvar bool
func init () {
flag . BoolVarP ( & flagvar , "boolname" , "b" , true , "help message" )
}
flag . VarP ( & flagVal , "varname" , "v" , "help message" )
В командной строке можно использовать сокращенные буквы с одинарным тире. Булевы флаги сокращений можно комбинировать с другими флагами сокращений.
Набор флагов командной строки по умолчанию контролируется функциями верхнего уровня. Тип FlagSet позволяет определять независимые наборы флагов, например, для реализации подкоманд в интерфейсе командной строки. Методы FlagSet аналогичны функциям верхнего уровня для установки флагов командной строки.
После создания флага можно установить pflag.NoOptDefVal для данного флага. Это немного меняет значение флага. Если флаг имеет NoOptDefVal и флаг установлен в командной строке без опции, флаг будет установлен в NoOptDefVal. Например, дано:
var ip = flag . IntP ( "flagname" , "f" , 1234 , "help message" )
flag . Lookup ( "flagname" ). NoOptDefVal = "4321"
Результатом будет что-то вроде
Разобранные аргументы | Результирующее значение |
---|---|
--flagname=1357 | ip=1357 |
--flagname | ip=4321 |
[ничего] | ip=1234 |
--flag // boolean flags, or flags with no option default values
--flag x // only on flags without a default value
--flag=x
В отличие от пакета flag, одиночное тире перед опцией означает нечто иное, чем двойное тире. Одиночные тире обозначают серию сокращенных букв флагов. Все, кроме последней сокращенной буквы, должны быть логическими флагами или флагами со значением по умолчанию.
// boolean or flags where the 'no option default value' is set
-f
-f=true
-abc
but
-b true is INVALID
// non-boolean and flags without a 'no option default value'
-n 1234
-n=1234
-n1234
// mixed
-abcs "hello"
-absd="hello"
-abcs1234
Разбор флага прекращается после терминатора "--". В отличие от пакета flag, флаги могут перемежаться аргументами в любом месте командной строки до этого терминатора.
Целочисленные флаги принимают значения 1234, 0664, 0x1234 и могут быть отрицательными. Логические флаги (в длинной форме) принимают значения 1, 0, t, f, true, false, TRUE, FALSE, True, False. Флаги продолжительности принимают любые входные данные, действительные для time.ParseDuration.
Можно установить собственное имя флага «функция нормализации». Он позволяет изменять имена флагов как при создании в коде, так и при использовании в командной строке в некоторую «нормализованную» форму. Для сравнения используется «нормализованная» форма. Ниже приведены два примера использования пользовательской функции нормализации.
Пример №1 : Вам нужны -, _ и . во флагах для сравнения то же самое. он же --my-flag == --my_flag == --my.flag
func wordSepNormalizeFunc ( f * pflag. FlagSet , name string ) pflag. NormalizedName {
from := [] string { "-" , "_" }
to := "."
for _ , sep := range from {
name = strings . Replace ( name , sep , to , - 1 )
}
return pflag . NormalizedName ( name )
}
myFlagSet . SetNormalizeFunc ( wordSepNormalizeFunc )
Пример №2 : Вы хотите использовать псевдонимы для двух флагов. он же --old-flag-name == --new-flag-name
func aliasNormalizeFunc ( f * pflag. FlagSet , name string ) pflag. NormalizedName {
switch name {
case "old-flag-name" :
name = "new-flag-name"
break
}
return pflag . NormalizedName ( name )
}
myFlagSet . SetNormalizeFunc ( aliasNormalizeFunc )
Можно объявить флаг устаревшим или просто его сокращение. Отказ от использования устаревшего флага/сокращения скрывает его из текста справки и печатает сообщение об использовании, когда используется устаревший флаг/сокращение.
Пример №1 . Вы хотите объявить устаревшим флаг с именем «badflag», а также сообщить пользователям, какой флаг им следует использовать вместо него.
// deprecate a flag by specifying its name and a usage message
flags . MarkDeprecated ( "badflag" , "please use --good-flag instead" )
При этом «badflag» скрывается из текста справки и печатается Flag --badflag has been deprecated, please use --good-flag instead
когда используется «badflag».
Пример №2 . Вы хотите сохранить имя флага «noshorthandflag», но отказаться от его короткого имени «n».
// deprecate a flag shorthand by specifying its flag name and a usage message
flags . MarkShorthandDeprecated ( "noshorthandflag" , "please use --noshorthandflag only" )
Это скроет короткое имя «n» из текста справки и выведет Flag shorthand -n has been deprecated, please use --noshorthandflag only
тогда, когда используется сокращение «n».
Обратите внимание, что здесь важно сообщение об использовании, и оно не должно быть пустым.
Флаг можно пометить как скрытый, то есть он по-прежнему будет работать как обычно, однако не будет отображаться в тексте использования/справке.
Пример : у вас есть флаг с именем «secretFlag», который вам нужен только для внутреннего использования, и вы не хотите, чтобы он отображался в тексте справки или чтобы текст его использования был доступен.
// hide a flag by specifying its name
flags . MarkHidden ( "secretFlag" )
pflag
позволяет отключить сортировку флагов для справок и сообщений об использовании.
Пример :
flags . BoolP ( "verbose" , "v" , false , "verbose output" )
flags . String ( "coolflag" , "yeaah" , "it's really cool flag" )
flags . Int ( "usefulflag" , 777 , "sometimes it's very useful" )
flags . SortFlags = false
flags . PrintDefaults ()
Выход :
-v, --verbose verbose output
--coolflag string it's really cool flag (default "yeaah")
--usefulflag int sometimes it's very useful (default 777)
Чтобы поддерживать флаги, определенные с помощью пакета flag
Go, их необходимо добавить в набор флагов pflag
. Обычно это необходимо для поддержки флагов, определенных сторонними зависимостями (например, golang/glog
).
Пример : вы хотите добавить флаги Go в набор флагов CommandLine
import (
goflag "flag"
flag "github.com/spf13/pflag"
)
var ip * int = flag . Int ( "flagname" , 1234 , "help message for flagname" )
func main () {
flag . CommandLine . AddGoFlagSet ( goflag . CommandLine )
flag . Parse ()
}
Вы можете просмотреть полную справочную документацию пакета pflag на сайте godoc.org или в стандартной системе документации go, запустив godoc -http=:6060
и перейдя по адресу http://localhost:6060/pkg/github.com/spf13/pflag. после установки.