在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
CLI或者“command line interface”是用户在命令行下交互的程序。由于通过将程序编译到一个静态文件中来减少依赖,一次Go特别适合开发CLI程序。如果你编写过安装时需要各种依赖的CLI程序你就知道这个是有多重要了。 Arguments大多数CLI程序都需要输入一些参数。Go 语言将这些参数以字符串slice处理。 var Args []string 查找当前应用的名字。 package main import ( "fmt" "os" ) func main() { // Program Name is always the first (implicit) argument cmd := os.Args[0] fmt.Printf("Program Name: %s\n", cmd) } 这个应用再code/example1下,你可以用一下命令编译运行: go build
./example1 输出的结果是: Program Name: ./example1 判断传入程序的参数数量为了确定有多少参数传入,可以计算所有参数的长度减1(记住,第一个参数总是程序的名字)。或者可以直接从os.Args[1:]来判断他的长度。 package main import ( "fmt" "os" ) func main() { argCount := len(os.Args[1:]) fmt.Printf("Total Arguments (excluding program name): %d\n", argCount) } 运行./example2 得到的结果将是0。运行./example2 -foo=bar 得到的记过将是1。 遍历参数下面是一个很快速的遍历参数的例子。 package main import ( "fmt" "os" ) func main() { for i, a := range os.Args[1:] { fmt.Printf("Argument %d is %s\n", i+1, a) } } Running the program with ./example3 -local u=admin --help results in: Argument 1 is -local Argument 2 is u=admin Argument 3 is --help Flag 包目前为止我们已经知道如何在一个程序中查找参数的基本的方法。在这个级别查询他们并且将他们赋值给我们的程序是很麻烦的。所有就有了Flag包。 package main import ( "flag" "fmt" ) func main() { var port int flag.IntVar(&port, "p", 8000, "specify port to use. defaults to 8000.") flag.Parse() fmt.Printf("port = %d", port) } 我们首先做的是设置一个int类型的默认值是8000,并且有文字提示的标识。 Usage of ./example4: -p=8000: specify port to use. defaults to 8000. flag.Args()很多CLI程序同时包含有标识和没有标识的参数。flag.Args() 将会直接返回哪些没有标识的参数。 package main import ( "flag" "fmt" ) func main() { var port int flag.IntVar(&port, "p", 8000, "specify port to use. defaults to 8000.") flag.Parse() fmt.Printf("port = %d\n", port) fmt.Printf("other args: %+v\n", flag.Args()) } port = 9000 other args: [foo=10 -bar] flag只要找到一个不包含的flag就会立即停止查询。 无效的flag参数Go是一个强语言类型,所以如果我们传递一个string给一个int类型的flag,它将会提示我们: package main import ( "flag" "fmt" ) func main() { var port int flag.IntVar(&port, "p", 8000, "specify port to use. defaults to 8000") flag.Parse() fmt.Printf("port = %d", port) } invalid value “foo” for flag -p: strconv.ParseInt: parsing “foo”: invalid syntax Usage of ./example6: -p=8000: specify port to use. defaults to 8000 flag不仅会提示我们输入错误,同时还会输出默认的使用方法。 flag.Usageflag包声明了一个Usage的方法。这样我们就可以输出我们想要输出的Usage了。 package main import ( "flag" "fmt" "os" ) func main() { flag.Usage = func() { fmt.Printf("Usage of %s:\n", os.Args[0]) fmt.Printf(" example7 file1 file2 ...\n") flag.PrintDefaults() } flag.Parse() } Usage of ./example7:
example7 file1 file2 … 获取输入目前为止我们只是通过CLI输出了信息,但是不接受任何输入。我们可以基本的fmt.Scanf()来捕捉输入。 package main import "fmt" func main() { var guessColor string const favColor = "blue" for { fmt.Println("Guess my favorite color:") if _, err := fmt.Scanf("%s", &guessColor); err != nil { fmt.Printf("%s\n", err) return } if favColor == guessColor { fmt.Printf("%q is my favorite color!", favColor) return } fmt.Printf("Sorry, %q is not my favorite color. Guess again.\n", guessColor) } } bufio.Scannerfmt.Scanf 对于简单的输入很有效,但是有时候我们可能需要一整行的数据。 package main import ( "bufio" "fmt" "os" ) func main() { scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { line := scanner.Text() if line == "exit" { os.Exit(0) } fmt.Println(line) // Println will add back the final '\n' } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "reading standard input:", err) } } 这是一个基本的echo程序,如果要退出直接输入exit即可。 一个基本的cat程序你应该用过很多次cat程序了。我们将会把这篇博客学到的只是融合在一起构建一个基本的cat程序。 package main import ( "flag" "fmt" "io" "os" ) func main() { flag.Usage = func() { fmt.Printf("Usage of %s:\n", os.Args[0]) fmt.Printf(" cat file1 file2 ...\n") flag.PrintDefaults() } flag.Parse() if flag.NArg() == 0 { flag.Usage() os.Exit(1) } for _, fn := range flag.Args() { f, err := os.Open(fn); if err != nil { panic(err) } _, err = io.Copy(os.Stdout, f) if err != nil { panic(err) } } } 帮助 对于帮助我们在上面已经讲了,但是还没有明确的定义 上面这些都会触发help。 总结本篇博客中只是讲了一些CLI的基本用法。如果想要学习更多,可以查看这些包的godoc 其他的命令行库还有一些第三方库可以让写CLI程序更简单: |
请发表评论