介绍go中的命令行参数, 命令行标志, 命令行子命令和环境变量
Command-Line Arguments 命令行参数是参数化程序执行的常用方法。例如,go run hello.go 在 go 程序中使用了 run 和 hello.go 参数。
command-line-arguments.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package mainimport ( "fmt" "os" ) func main () { argsWithProg := os.Args argsWithoutProg := os.Args[1 :] arg := os.Args[3 ] fmt.Println(argsWithProg) fmt.Println(argsWithoutProg) fmt.Println(arg) }
要尝试使用命令行参数,最好先用 go build 生成二进制文件。
log 1 2 3 4 5 $ go build command-line-arguments.go $ ./command-line-arguments a b c d [./command-line-arguments a b c d] [a b c d] c
接下来,我们将学习使用标记进行更高级的命令行处理。
Command-Line Flags 命令行标志是为命令行程序指定选项的常用方法。例如,在 wc -l 中,-l 就是一个命令行标志。
command-line-flags.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package mainimport ( "flag" "fmt" ) func main () { wordPtr := flag.String("word" , "foo" , "a string" ) numbPtr := flag.Int("numb" , 42 , "an int" ) forkPtr := flag.Bool("fork" , false , "a bool" ) var svar string flag.StringVar(&svar, "svar" , "bar" , "a string var" ) flag.Parse() fmt.Println("word:" , *wordPtr) fmt.Println("numb:" , *numbPtr) fmt.Println("fork:" , *forkPtr) fmt.Println("svar:" , svar) fmt.Println("tail:" , flag.Args()) }
要试用命令行标志程序,最好先编译它,然后直接运行生成的二进制文件。
log 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 $ go build command-line-flags.go # 试运行已构建的程序,首先为所有标志赋值。 $ ./command-line-flags -word=opt -numb=7 -fork -svar=flag word: opt numb: 7 fork: true svar: flag tail: [] # 请注意,如果省略标记,它们会自动使用默认值。 $ ./command-line-flags -word=opt word: opt numb: 42 fork: false svar: bar tail: [] # 可以在任何标志之后提供尾部位置参数。 $ ./command-line-flags -word=opt a1 a2 a3 word: opt ... tail: [a1 a2 a3] # 请注意,flag 包要求所有标志都出现在位置参数之前(否则标志将被解释为位置参数)。 $ ./command-line-flags -word=opt a1 a2 a3 -numb=7 word: opt numb: 42 fork: false svar: bar tail: [a1 a2 a3 -numb=7] # 使用 -h 或 --help 标志,可为命令行程序自动生成帮助文本。 $ ./command-line-flags -h Usage of ./command-line-flags: -fork=false: a bool -numb=42: an int -svar="bar": a string var -word="foo": a string # 如果您提供的标志未在标志包中指定,程序将打印错误信息并再次显示帮助文本。 $ ./command-line-flags -wat flag provided but not defined: -wat Usage of ./command-line-flags: ...
Command-Line Subcommands 有些命令行工具,如 go 工具或 git,有许多子命令,每个子命令都有自己的标志集。例如,go build 和 go get 是 go 工具的两个不同子命令。通过 flag 包,我们可以轻松定义拥有自己标志的简单子命令。
command-line-subcommands.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package mainimport ( "flag" "fmt" "os" ) func main () { fooCmd := flag.NewFlagSet("foo" , flag.ExitOnError) fooEnable := fooCmd.Bool("enable" , false , "enable" ) fooName := fooCmd.String("name" , "" , "name" ) barCmd := flag.NewFlagSet("bar" , flag.ExitOnError) barLevel := barCmd.Int("level" , 0 , "level" ) if len (os.Args) < 2 { fmt.Println("expected 'foo' or 'bar' subcommands" ) os.Exit(1 ) } switch os.Args[1 ] { case "foo" : fooCmd.Parse(os.Args[2 :]) fmt.Println("subcommand 'foo'" ) fmt.Println(" enable:" , *fooEnable) fmt.Println(" name:" , *fooName) fmt.Println(" tail:" , fooCmd.Args()) case "bar" : barCmd.Parse(os.Args[2 :]) fmt.Println("subcommand 'bar'" ) fmt.Println(" level:" , *barLevel) fmt.Println(" tail:" , barCmd.Args()) default : fmt.Println("expected 'foo' or 'bar' subcommands" ) os.Exit(1 ) } }
log 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $ go build command-line-subcommands.go # 首先调用 foo 子命令。 $ ./command-line-subcommands foo -enable -name=joe a1 a2 subcommand 'foo' enable: true name: joe tail: [a1 a2] # 现在试试 bar。 $ ./command-line-subcommands bar -level 8 a1 subcommand 'bar' level: 8 tail: [a1] # 但 bar 不接受 foo 的标志。 $ ./command-line-subcommands bar -enable a1 flag provided but not defined: -enable Usage of bar: -level int level
接下来,我们来看看环境变量,这是参数化程序的另一种常用方法。
Environment Variables 环境变量是向 Unix 程序传递配置信息的通用机制。让我们来看看如何设置、获取和列出环境变量。
environment-variables.go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package mainimport ( "fmt" "os" "strings" ) func main () { os.Setenv("FOO" , "1" ) fmt.Println("FOO:" , os.Getenv("FOO" )) fmt.Println("BAR:" , os.Getenv("BAR" )) fmt.Println() for _, e := range os.Environ() { pair := strings.SplitN(e, "=" , 2 ) fmt.Println(pair[0 ]) } }
运行程序后发现,我们拾取了在程序中设置的 FOO 值,但 BAR 是空的。
log 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ go run environment-variables.go FOO: 1 BAR: # 环境中的 keys 列表将取决于您的特定机器。 TERM_PROGRAM PATH SHELL ... FOO # 如果我们先在环境中设置 BAR,运行中的程序就会选择该值。 $ BAR=2 go run environment-variables.go FOO: 1 BAR: 2 ...
参考链接