CLI或者“command line interface”是用户在命令行下交互的程序。由于通过将程序编译到一个静态文件中来减少依赖,一次Go特别适合开发CLI程序。如果你编写过安装时需要各种依赖的CLI程序你就知道这个是有多重要了。
   在这篇博客中我们将介绍使用Go开发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,并且有文字提示的标识。
   为了让flag包对设置的变量赋值,需要是用flag.Parse()方法。
   不加参数的运行这个程序得到的结果是port = 8000,因为我们明确的指定了如果没有参数传递给port,那么就采用默认的8000.
   运行./example4 -p=9000 结果是 port = 9000
   同事flag提供了 “program useage”的输出。如果我们运行 ./example4 -help 我们会得到:

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())
}

运行./example5 -p=9000 foo=10 -bar 将会得到:

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)
}

运行程序./example6 -p=foo 得到的结果是:

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.Usage

   flag包声明了一个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()
}

运行./example7 –help 得到的结果是:

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.Scanner

   fmt.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)
}
}
}

CLI:如何使用Go开发命令行的更多相关文章

  1. Apache Commons CLI 开发命令行工具示例

    概念说明Apache Commons CLI 简介 虽然各种人机交互技术飞速发展,但最传统的命令行模式依然被广泛应用于各个领域:从编译代码到系统管理,命令行因其简洁高效而备受宠爱.各种工具和系统都 提 ...

  2. 使用 Apache Commons CLI 开发命令行工具示例

    Apache Commons CLI 简介 Apache Commons CLI 是 Apache 下面的一个解析命令行输入的工具包,该工具包还提供了自动生成输出帮助文档的功能. Apache Com ...

  3. rocketmq番外篇(一):开发命令行

    匠心零度 转载请注明原创出处,谢谢! 说在前面 虽然是以rocketmq引出的开发命令行,但是任何java应用如果需要都可以借鉴引用,也是通用技术. 主题 rocketmq使用例子 Apache Co ...

  4. Go使用flag包开发命令行工具

    flag包是Go语言标准库提供用来解析命令行参数的包,使得开发命令行工具更为简单 常用方法 1.flag.Usage 输出使用方法,如linux下ls -h的帮助输出 2.flag.Type(参数名, ...

  5. 用PHP开发命令行工具

    介绍 用过laravel开发过项目的都应该用过artisan,通过artisan我们可以在命令行中创建控制器类,Eloquent类等,今天我们将通过php来开发命令行工具 开发环境与工具 使用vagr ...

  6. CLI:使用Go开发命令行应用

      原文地址 CLI或者"command line interface"是用户在命令行下交互的程序.由于通过将程序编译到一个静态文件中来减少依赖,一次Go特别适合开发CLI程序.如 ...

  7. Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式

    昨天通过几个小程序以及Hangout源码学习了CLI的基本使用,今天就来尝试翻译一下CLI的官方使用手册. 下面将会通过几个部分简单的介绍CLI在应用中的使用场景. 昨天已经联系过几个基本的命令行参数 ...

  8. Android 开发命令行完全攻略

    作为命令行的爱好者,我想写这个主题已经有好一段时间了.除了显得很酷之外,命令行的使用能够提高我们的开发效率,因为相比通过鼠标点击一系列的菜单选项,使用键盘输入几个字符并点击 TAB 健显然会快很多. ...

  9. node.js 开发命令行工具 发布npm包

    新建一个文件夹“nodecmd”: 在nodecmd下新建文件夹bin: 在bin文件夹下新建JavaScript文件hello.js #!/usr/bin/env node console.log( ...

随机推荐

  1. React 性能优化总结

    初学者对React可能满怀期待,觉得React可能完爆其它一切框架,甚至不切实际地认为React可能连原生的渲染都能完爆--对框架的狂热确实会出现这样的不切实际的期待.让我们来看看React的官方是怎 ...

  2. 设计模式C#实现(十三)——享元模式(蝇量模式)

    意图 0 适用性 1 结构 2 实现 3 效果 4 参考 5 意图 运用共享技术有效地支持大量细粒度的对象. 适用性 当以下情况都成立时使用: 一个程序使用了大量的对象 完全由于使用大量对象造成很大存 ...

  3. 【转】深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接

    [原文]:http://www.jb51.net/article/39432.htm 1.内联接(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接.    ...

  4. 两种交换机配置模式,以配置基于端口划分的VLAN为例

    关于交换机的配置模式,大体上可以分为两类:其一以CISCO交换机为代表的配置模式,其二以Huawei.H3C交换机为代表的配置模式.其实这两种配置模式并没有本质的不同,只是配置的命令名称和配置方式存在 ...

  5. NSLogger 简单用法总结

    NSLogger 支持在同一个本地网络下,移动 App产生的日志,通过 Bonjour 网络传送到电脑上查看日志信息. 1.具体用法: 在移动App项目里,添加3个文件: LoggerCommon.h ...

  6. redis 源码阅读 数值转字符 longlong2str

    redis 在底层中会把long long转成string 再做存储. 主个功能是在sds模块里. 下面两函数是把long long 转成 char  和   unsiged long long 转成 ...

  7. Mysql日志解析

    修改Mysql配置 Mysql配置地址为: C:\Program Files (x86)\MySQL\MySQL Server 5.5 如果无法修改可以把my.ini拷贝出来,修改完后,再拷贝回去! ...

  8. [WPF系列]-高级部分 Shadowed TextBox

    Download Solution ShadowedTextBoxExample.zip (70.3 KB) Usage <local:ShadowedTextBox Label="F ...

  9. 关于安装ruby brew 提示失败

    Error running 'requirements_osx_brew_update_system ruby-1.9.3-p551', showing last 15 lines of /Users ...

  10. BZOJ 2120 数颜色&2453 维护队列 [带修改的莫队算法]【学习笔记】

    2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 3665  Solved: 1422[Submit][Status][Discuss] ...