пятница, 29 мая 2020 г.

Пакет flag в Golang

Пакет flag реализует синтаксический анализ флага командной строки.

Применение

Определите флаги, используя flag.String(), Bool(), Int() и т. д.

Здесь объявляется целочисленный флаг -flagname, хранящийся в указателе ip, с типом *int.

import "flag"
var ip = flag.Int("flagname", 1234, "вспомогательное сообщение для flagname")

При желании вы можете привязать флаг к переменной, используя функции Var().

var flagvar int
func init() {
    flag.IntVar(&flagvar, "flagname", 1234, "вспомогательное сообщение для flagname")
}

Или вы можете создать пользовательские флаги, которые удовлетворяют интерфейсу Value (с получателями указателей), и связать их с анализом флага с помощью

flag.Var(&flagVal, "name", "вспомогательное сообщение для flagname")

Для таких флагов значением по умолчанию является только начальное значение переменной.

После того, как все флаги определены, вызовите

flag.Parse()

чтобы разобрать командную строку в определенные флаги.

Флаги могут быть использованы напрямую. Если вы используете сами флаги, они все являются указателями; если вы привязываетесь к переменным, это значения.

fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)

После синтаксического анализа аргументы, следующие за флагами, доступны как флаг slice.Args() или отдельно как flag.Arg(i). Аргументы индексируются от 0 до flag.NArg()-1.

Синтаксис флага командной строки

Разрешены следующие формы:

-flag
-flag=x
-flag x  // только не булевы флаги

Можно использовать один или два знака минус; они эквивалентны. Последняя форма недопустима для логических флагов, потому что значение команды

cmd -x *

где * - это подстановочный знак оболочки Unix, он изменится, если есть файл с именем 0, false и т. д. Вы должны использовать форму -flag=false, чтобы отключить логический флаг.

Разбор флага останавливается непосредственно перед первым аргументом без флага ("-" является аргументом без флага) или после терминатора "-".

Целочисленные флаги принимают 1234, 0664, 0x1234 и могут быть отрицательными. Булевы флаги могут быть:

1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False

Флаги продолжительности принимают любой ввод, действительный для time.ParseDuration.

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

Пример использования flag

// Эти примеры демонстрируют 
// более сложное использование пакета flag.
package main

import (
    "errors"
    "flag"
    "fmt"
    "strings"
    "time"
)

// Пример 1: одиночный строковый флаг 
// с именем "species" со значением по умолчанию "gopher".
var species = flag.String("species", "gopher", "the species we are studying")

// Пример 2. Два флага, совместно использующих переменную, 
// поэтому мы можем иметь сокращение.
// Порядок инициализации не определен, поэтому убедитесь, 
// что оба используют то же значение по умолчанию. 
// Они должны быть настроены с помощью функции init.
var gopherType string

func init() {
    const (
        defaultGopher = "pocket"
        usage = "the variety of gopher"
    )
    flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
    flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)")
}

// Пример 3: пользовательский тип флага, 
// срез продолжительностей.
type interval []time.Duration

// String - это метод для форматирования значения флага, 
// часть интерфейса flag.Value.
// Вывод метода String будет использоваться в диагностике.
func (i *interval) String() string {
    return fmt.Sprint(*i)
}

// Set - это метод для установки значения флага, 
// часть интерфейса flag.Value.
// Аргументом Set является строка, 
// которая будет проанализирована для установки флага.
// Это список через запятую, поэтому мы разбиваем его.
func (i *interval) Set(value string) error {
    // Если мы хотим разрешить установку флага несколько раз,
    // накапливая значения, мы удалили бы этот оператор if.
    // Это позволило бы использовать такие, как
    // -deltaT 10s -deltaT 15s
    // и другие комбинации.
    if len(*i) > 0 {
        return errors.New("interval flag already set")
    }
    for _, dt := range strings.Split(value, ",") {
        duration, err := time.ParseDuration(dt)
        if err != nil {
            return err
        }
        *i = append(*i, duration)
    }
    return nil
}

// Определяем флаг для накопления длительностей. 
// Потому что у него есть особый тип,
// нам нужно использовать функцию Var 
// и поэтому создавать флаг во время init.

var intervalFlag interval

func init() {
    // Привязать флаг командной строки 
    // к переменной intervalFlag и
    // установить сообщение об использовании.
    flag.Var(&intervalFlag, "deltaT", "разделенный запятыми список интервалов, используемых между событиями")
}

func main() {
    // Все интересные части с переменными, 
    // объявленными выше, но
    // чтобы позволить пакету flag видеть флаги, 
    // определенные там, нужно
    // выполнить, как правило, 
    // в начале main (не init!):
    
    flag.Parse()
}


Читайте также:


Комментариев нет:

Отправить комментарий