GO学习笔记 - 命令行解析
source link: https://www.tuicool.com/articles/nEfeiuY
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
image
本文主题:基于os.Args与flag实现Golang命令行解析。
小慢哥的原创文章,欢迎转载
目录
▪ 一. os.Args
▪ 二. flag
▪ 三. 结合os.Args与flag实现子命令
▪ 附. 参考文档
一. os.Args
os.Args用于获取通过命令行传入的参数
▷ os.Args[0] :程序执行路径
▷ os.Args[1] :第1个参数
▷ os.Args[2] :第2个参数
▷ len(os.Args) :参数数量
示例如下
package main import ( "fmt" "os" ) func main() { fmt.Println("Program:", os.Args[0]) for i, v := range os.Args[1:] { fmt.Printf("Arg[%d]: %v\n", i, v) } }
测试效果
# 编译执行 go build arg.go ./arg foo "hello world" bar # 输出 Program: ./arg Arg[0]: foo Arg[1]: hello world Arg[2]: bar
二. flag
golang内置的flag模块可以实现命令行flag解析。
什么是flag,举例说明(加粗部分就是flag):
▷ wc -l
▷ ./configure --prefix=/usr/local/nginx
示例如下(摘取自gobyexample)
package main import ( "flag" "fmt" ) func main() { // flag.String返回的是指针 // word表示参数名,foo表示默认值,a string表示参数释义(在-h或解析异常时候会看到) // flag.Int、flag.Bool与flag.String同理,不再赘述 wordPtr := flag.String("word", "foo", "a string") numbPtr := flag.Int("numb", 42, "an int") boolPtr := flag.Bool("fork", false, "a bool") // flag.StringVar返回的是非指针 var svar string flag.StringVar(&svar, "svar", "bar", "a string var") // 进行flag解析 flag.Parse() fmt.Println("word:", *wordPtr) fmt.Println("numb:", *numbPtr) fmt.Println("fork:", *boolPtr) fmt.Println("svar:", svar) fmt.Println("tail:", flag.Args()) }
测试效果
# 编译 go build flag.go ./flag -word=opt -numb=7 -fork -svar=flag # 输出 word: opt numb: 7 fork: true svar: flag tail: [] ./flag -word=opt # 输出 word: opt numb: 42 fork: false svar: bar tail: [] ./flag -word=opt a1 a2 a3 # 输出 word: opt numb: 42 fork: false svar: bar tail: [a1 a2 a3] ./flag -word=opt a1 a2 a3 -numb=7 # 输出 word: opt numb: 42 fork: false svar: bar tail: [a1 a2 a3 -numb=7] ./flag -h # 输出 Usage of ./flag: -fork a bool -numb int an int (default 42) -svar string a string var (default "bar") -word string a string (default "foo") ./flag -wat # 输出 flag provided but not defined: -wat Usage of ./flag: ...
该例子,在测试时候只使用了“单横线+参数名”,实际有4种方式,效果是相同的
-word opt -word=opt --word opt --word=opt
三. 结合os.Args与flag实现子命令
如果想实现子命令效果,例如:
▷ docker ps --last 10
▷ docker images --help
这需要将os.Args和flag结合使用。基本原理:创建多个flag集合(即*flag.FlagSet),每个flag集合对应不同的os.Args
示例如下(摘取自gobyexample)
package main import ( "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) } }
测试效果
# 编译 go build subflag.go ./subflag foo -enable -name=joe a1 a2 # 输出 subcommand 'foo' enable: true name: joe tail: [a1 a2] ./subflag bar -level 8 a1 # 输出 subcommand 'bar' level: 8 tail: [a1] ./subflag bar -enable a1 # 输出 flag provided but not defined: -enable Usage of bar: -level int level
附. 参考文档
# os.Args https://gobyexample.com/command-line-arguments # flag https://gobyexample.com/command-line-flags # 子命令 https://gobyexample.com/command-line-subcommands
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK