Vá em pacotes da bandeira.

Este artigo Endereço original: https://github.com/polaris1119/The-Golang-Standard-Library-by-Example/edit/master/chapter13/13.1.md
enquanto o programa de linha de comando escrita (ferramentas, servidores), parâmetros de comando análise é uma exigência comum. Várias línguas costumam fornecer um método para analisar parâmetros de linha de comando ou biblioteca para facilitar os programadores a usar. Se os argumentos de linha de comando puramente para escrever a sua própria análise de código para mais complexa, ou muito extenuante. Fornecidas no go biblioteca padrão em um pacote: flagconveniente de análise de linha de comando.

Nota: Vários Distinção Conceição

  1. argumentos de linha de comando (ou parâmetros): refere-se aos parâmetros fornecidos para executar o programa
  2. linha de comando parâmetros foram definidos: refere-se ao processo definido pelos parâmetros deste forma como flag.Xxx
  3. Non bandeira (non-flag) argumentos de linha de comando (parâmetros de linha de comando ou retidos): explicado mais tarde

Exemplos de Utilização

Nós nginx por exemplo, a implementação de nginx -h, a saída é a seguinte:

nginx version: nginx/1.10.0
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/local/nginx/)
  -c filename   : set configuration file (default: conf/nginx.conf)
  -g directives : set global directives out of configuration file

Nós flagalcançar nginx semelhante esta saída, crie um arquivo nginx.go, tem o seguinte teor:

package main

import (
	"flag"
	"fmt"
	"os"
)

// 实际中应该用更好的变量名
var (
	h bool

	v, V bool
	t, T bool
	q    *bool

	s string
	p string
	c string
	g string
)

func init() {
	flag.BoolVar(&h, "h", false, "this help")

	flag.BoolVar(&v, "v", false, "show version and exit")
	flag.BoolVar(&V, "V", false, "show version and configure options then exit")

	flag.BoolVar(&t, "t", false, "test configuration and exit")
	flag.BoolVar(&T, "T", false, "test configuration, dump it and exit")

	// 另一种绑定方式
	q = flag.Bool("q", false, "suppress non-error messages during configuration testing")

	// 注意 `signal`。默认是 -s string,有了 `signal` 之后,变为 -s signal
	flag.StringVar(&s, "s", "", "send `signal` to a master process: stop, quit, reopen, reload")
	flag.StringVar(&p, "p", "/usr/local/nginx/", "set `prefix` path")
	flag.StringVar(&c, "c", "conf/nginx.conf", "set configuration `file`")
	flag.StringVar(&g, "g", "conf/nginx.conf", "set global `directives` out of configuration file")

	// 改变默认的 Usage
	flag.Usage = usage
}

func main() {
	flag.Parse()

	if h {
		flag.Usage()
	}
}

func usage() {
	fmt.Fprintf(os.Stderr, `nginx version: nginx/1.10.0
Usage: nginx [-hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
`)
	flag.PrintDefaults()
}

Realizada: Vai correr nginx.go -H, (ou ir construção -o nginx && ./nginx -h) de saída é a seguinte:

nginx version: nginx/1.10.0
Usage: nginx [-hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -T	test configuration, dump it and exit
  -V	show version and configure options then exit
  -c file
    	set configuration file (default "conf/nginx.conf")
  -g directives
    	set global directives out of configuration file (default "conf/nginx.conf")
  -h	this help
  -p prefix
    	set prefix path (default "/usr/local/nginx/")
  -q	suppress non-error messages during configuration testing
  -s signal
    	send signal to a master process: stop, quit, reopen, reload
  -t	test configuration and exit
  -v	show version and exit

Cuidadosamente apreciado que o exemplo acima, se não é entendido, depois de ler o seguinte Volte explicação e olhar.

flag saco Overview

flag implementos pacote parsing parâmetros de linha de comando.

Há duas maneiras de definir bandeiras

1) flag.Xxx (), que Xxxpode ser Int, String semelhantes; retorna um ponteiro para o tipo apropriado, tais como:

var ip = flag.Int("flagname", 1234, "help message for flagname")

2) flag.XxxVar (), a bandeira ligado a uma variável, tais como:

var flagvar int
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")

Valor personalizado

Além disso, você pode criar uma bandeira personalizada, desde que a interface pode ser implementada flag.Value (reivindicação receiverponteiro), a bandeira neste momento pode ser definido por:

flag.Var(&flagVal, "name", "help message for flagname")

Por exemplo, a minha análise favorito linguagem de programação, esperamos resolver diretamente à fatia, podemos definir o seguinte valor:

type sliceValue []string

func newSliceValue(vals []string, p *[]string) *sliceValue {
	*p = vals
	return (*sliceValue)(p)
}

func (s *sliceValue) Set(val string) error {
	*s = sliceValue(strings.Split(val, ","))
	return nil
}

func (s *sliceValue) Get() interface{} { return []string(*s) }

func (s *sliceValue) String() string { return strings.Join([]string(*s), ",") }

Depois de usar:

var languages []string
flag.Var(newSliceValue([]string{}, &languages), "slice", "I like programming `languages`")

Por assim -slice "go,php"passando os parâmetros de tal forma uma languagesobtido é [go, php].

Duração desta bandeira do tipo não-básico de suporte utilizada é semelhante desta forma.

bandeira análise

Afinal a bandeira definido, chamando flag.Parse()para a resolução.

A sintaxe da bandeira linha de comando pode assumir três formas:

-flag // 只支持 bool 类型
-flag=x
-flag x // 只支持非 bool 类型

A terceira forma que só pode ser usado para o tipo não-bool de bandeira, a razão é: Se isso acontecer, então para este comando cmd -x *, se não houver um nome de arquivo é: 0 ou a mudança falsa vontade intenção e assim por diante, o comando do ( a razão para isso é porque o tipo bool apoio -flagesta forma, se o tipo bool não suporta -flagesta forma, você pode digitar bool e outros tipos de um mesmo processo. é por isso, Parse (), o tipo de bool para um tratamento especial) . Padrão é fornecido -flag, o valor correspondente é verdadeiro, caso contrário, flag.Bool/BoolVaro valor padrão especificado; se você quiser exibição é definido como uso falsa -flag=false.

Tipo int pode ser decimal, hexadecimal, octal, ou mesmo negativo, tipo bool pode ser 1, 0, t, f, verdadeiro, falso, TRUE, FALSE, True, False. Duração pode aceitar qualquer tipo de time.ParseDuration pode ser resolvido.

Tipos e funções

Antes de olhar para os tipos e funções, olhar para as variáveis.

ErrHelp: O tipo errado é usado quando os parâmetros de linha de comando especificado quando · -help` mas não definido.

Uso: Esta é uma função que define a saída de todos os argumentos de linha de comando e informações de ajuda (mensagem de uso). Em geral, quando um erro ao analisar parâmetros de linha de comando, a função é chamada. Podemos especificar sua própria função de Uso, a saber:flag.Usage = func(){}

função

ir biblioteca padrão, muitas vezes fazer:

Definição de um tipo, um número de maneiras; por conveniência, irá criar uma instância (genérico) deste tipo, para que ele possa usar diretamente o método de instância chamada. Por exemplo: de codificação / base 64 e fornece exemplo StdEncoding URLEncoding, uso: base64.StdEncoding.Encode ()

Bandeira no pacote utilizando modos similares, como exemplos CommandLine, mas foram adicionalmente encapsulado bandeira: a métodos redefinir FlagSet novamente, isto é, proporciona uma sequência de funções, e função simplesmente chamada instanciado o exemplo bom FlagSet: método de linha de comando. Desta forma, o usuário é tão chamada :. Flag.Parse () em vez de CommandLine.Parse bandeira (). (Ir 1.2 a partir da exportação de linha de comando, não previamente exportados)

Cada função não é descrita aqui em detalhe, do tipo descrito no processo.

Tipos (estruturas de dados)

1) ErrorHandling

type ErrorHandling int

Este tipo define a manipulação de erro quando o parâmetro de erro modo de análise. Isto define três tipos de constantes:

const (
	ContinueOnError ErrorHandling = iota
	ExitOnError
	PanicOnError
)

Três constantes utilizadas no método fonte parseOne FlagSet () de.

2) Bandeira

// A Flag represents the state of a flag.
type Flag struct {
	Name     string // name as it appears on command line
	Usage    string // help message
	Value    Value  // value as set
	DefValue string // default value (as text); for usage message
}

Tipo de bandeira representa um estado bandeira.

Por exemplo, para o comando: ./nginx -c /etc/nginx.confo código correspondente é:

flag.StringVar(&c, "c", "conf/nginx.conf", "set configuration `file`")

Exemplos da bandeira (pode flag.Lookup("c")ser obtido) correspondente para o valor de cada campo:

&Flag{
	Name: c,
	Usage: set configuration file,
	Value: /etc/nginx.conf,
	DefValue: conf/nginx.conf,
}

3) FlagSet

// A FlagSet represents a set of defined flags.
type FlagSet struct {
	// Usage is the function called when an error occurs while parsing flags.
	// The field is a function (not a method) that may be changed to point to
	// a custom error handler.
	Usage func()

	name string // FlagSet 的名字。CommandLine 给的是 os.Args[0]
	parsed bool // 是否执行过 Parse()
	actual map[string]*Flag // 存放实际传递了的参数(即命令行参数)
	formal map[string]*Flag // 存放所有已定义命令行参数
	args []string // arguments after flags // 开始存放所有参数,最后保留 非 flag(non-flag)参数
	exitOnError bool // does the program exit if there's an error?
	errorHandling ErrorHandling // 当解析出错时,处理错误的方式
	output io.Writer // nil means stderr; use out() accessor
}

4) Interface de Valor

// Value is the interface to the dynamic value stored in a flag.
// (The default value is represented as a string.)
type Value interface {
	String() string
	Set(string) error
}

Parâmetro Valor implementar todas as interfaces necessárias, pacote de bandeira, como int, float, bool outros implementa a interface. Com esta interface, podemos personalizar a bandeira. (Exemplos específicos acima foram dadas)

Os principais tipos de processos (incluindo tipo instanciação)

flag é principalmente FlagSet tipo de pacote.

Exemplos da maneira

NewFlagSet()Exemplos de FlagSet. Exemplos de pré-definido FlagSet CommandLinemaneira definida:

// The default set of command-line flags, parsed from os.Args.
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)

Visível, o padrão FlagSet instância ao analisar erro irá sair do programa.

Uma vez que o campo não é em FlagSet exportação, FlagSet Exemplo obtida de outro modo, tais como: FlagSet {} ou nova (FlagSet), ele deve ser chamado método Init (), e para inicializar nome ErrorHandling, ou o nome está vazia, como ErrorHandling ContinueOnError.

O método definido bandeira parâmetro

Este método sequcia tem duas formas, no início foi dito a diferença entre as duas abordagens. Estes métodos são utilizados para definir os parâmetros de um determinado tipo de bandeira.

Os parâmetros analíticos (Analisar)

func (f *FlagSet) Parse(arguments []string) error

Analisando bandeira definida na lista de parâmetros. O método não inclui um nome de comando argumentos de parâmetros, ou seja, deve ser os.Args [1:]. Na verdade, flag.Parse()a função fez exatamente isso:

// Parse parses the command-line flags from os.Args[1:].  Must be called
// after all flags are defined and before flags are accessed by the program.
func Parse() {
	// Ignore errors; CommandLine is set for ExitOnError.
	CommandLine.Parse(os.Args[1:])
}

O método deve ser o valor do parâmetro específico do parâmetro após a bandeira foi chamadas de acesso previamente definido.

Se um -helpparâmetro (ordem dada), mas não definido (sem código), o método retorna ErrHelpum erro. A linha de comando padrão, quando erro Parse vai sair do programa (ExitOnError).

Para uma melhor compreensão, olhamos para o Parse(arguments []string)código-fonte:

func (f *FlagSet) Parse(arguments []string) error {
	f.parsed = true
	f.args = arguments
	for {
		seen, err := f.parseOne()
		if seen {
			continue
		}
		if err == nil {
			break
		}
		switch f.errorHandling {
		case ContinueOnError:
			return err
		case ExitOnError:
			os.Exit(2)
		case PanicOnError:
			panic(err)
		}
	}
	return nil
}

Não verdadeiro método de método de resolução de parâmetros derivação parseOne.

Combinada parseOnemétodo, vamos explicar non-flage saco de documentos nesta frase:

Bandeira de análise pára pouco antes de o primeiro argumento não-bandeira ( "-" é um argumento não-flag) ou depois do terminator "-".

Precisamos saber quando parar de análise.

De acordo com Parse () condições de loop para a rescisão (sem levar em conta erros analíticos), sabemos que quando parseOne retorno false, niltempo, Parse analisar encerrado. Nós não consideramos a conclusão normal da análise. ParseOne olhada no código fonte descobriram que os dois retornos false, nil.

1) um primeiro parâmetro de não-bandeira

s := f.args[0]
if len(s) == 0 || s[0] != '-' || len(s) == 1 {
	return false, nil
}

Isto é, quando confrontados com uma separado "-" ou não "-" no início, parada de resolver. Por exemplo:

./nginx - -c 或 ./nginx -c construção

Em ambos os casos, -cele não vai ser resolvido corretamente. Como neste exemplo, "-" ou de construção (e os parâmetros subsequentes), chamamos non-flagparâmetros.

2) dois sucessivos "-"

if s[1] == '-' {
	num_minuses++
	if len(s) == 2 { // "--" terminates the flags
		f.args = f.args[1:]
		return false, nil
	}
}

Isto é, quando confrontado com dois consecutivos "-", a análise pára.

Descrição: que é "-" e "-" posição e "c" Este é o mesmo. Em outras palavras, o seguinte cenário não está aqui para dizer:

./nginx -c -

Aqui, "-" será tratada como um cvalor

parseOne o seguinte é um método de processamento -flag=xnesta forma, em seguida, -flagesta forma (tipo booleano) (boleano aqui foi especialmente concebido para), em seguida -flag xesta forma, finalmente, os exemplos de sucesso Parses bandeira mapa real armazenado no FlagSet no.

Além disso, em parseOne em tal sentença a:

f.args = f.args[1:]

Ou seja, cada executado com sucesso uma vez parseOne, f.args um a menos. Então, FlagSet os argumentos última estadia é que todos os non-flagparâmetros.

Arg (i int) 和 Args (), nArg (), nFlag ()

Arg (i int) e os Args () destes dois métodos é a obtenção do non-flagparâmetro; nArg () obtido non-flagnúmero; (isto é, o número de conjuntos de parâmetros) nFlag () para obter o comprimento real FlagSet.

Visita / VisitAll

Estas duas funções são usadas para acesso a FlatSet real e formal da Bandeira, e método de acesso específico é determinado pelo chamador.

PrintDefaults ()

Imprimir todos os padrões parâmetros definidos (chamada VisitAll conseguir), a saída padrão para o erro padrão, a menos que a saída FlagSet designado (por SetOutput () definição)

Definir (nome, cadeia de valor)

Definir um valor bandeira (bandeira por encontrar o nome correspondente)

resumo

Sugestão de uso: Embora o acima falou sobre muito, em geral, nós simplesmente definir bandeira, e, em seguida, analisar, apenas como um exemplo do início da mesma.

Se o seu projeto requer mais modo de análise de linha de comando avançado ou complexo, você pode usar https://github.com/urfave/cli  ou  https://github.com/spf13/cobra estes dois poderosa biblioteca.

Acho que você gosta

Origin www.cnblogs.com/MaxBaiSecurity/p/12651587.html
Recomendado
Clasificación