Go语言技术与应用(六):命令行工具开发基础
命令行工具在日常开发中用得很多,比如git、docker这些我们天天用的工具。Go语言写命令行程序特别方便,语法简单,编译后就是一个可执行文件,部署起来很轻松。
这篇文章会带你从零开始,学会用Go写命令行工具的基础知识。主要涉及两个核心内容:如何处理命令行参数和如何获取用户输入。
1. 命令行参数处理
1.1 os.Args基础用法
Go语言内置的os.Args
是个字符串切片,专门用来获取命令行参数。它有个特点:第一个元素永远是程序本身的名字,从第二个元素开始才是用户传入的参数。
来看个简单例子:
package mainimport ("fmt""os" // 别忘了导入os包
)func main() {// 检查是否有参数传入if len(os.Args) > 1 {fmt.Println("你传入的参数有:")// 从索引1开始遍历,跳过程序名for i, arg := range os.Args[1:] {fmt.Printf("参数%d: %s\n", i+1, arg)}} else {fmt.Println("没有传入任何参数")}// 顺便看看程序名是什么fmt.Printf("程序名: %s\n", os.Args[0])
}
1.2 实际应用场景
假设我们要写一个简单的文件操作工具,可以根据不同参数执行不同操作:
package mainimport ("fmt""os"
)func main() {if len(os.Args) < 2 {fmt.Println("用法: ./tool <命令> [参数]")fmt.Println("支持的命令: list, create, delete")return}command := os.Args[1] // 获取第一个参数作为命令switch command {case "list":fmt.Println("列出文件...")// 这里可以添加列出文件的逻辑case "create":if len(os.Args) < 3 {fmt.Println("create命令需要文件名参数")return}filename := os.Args[2]fmt.Printf("创建文件: %s\n", filename)// 这里可以添加创建文件的逻辑case "delete":if len(os.Args) < 3 {fmt.Println("delete命令需要文件名参数")return}filename := os.Args[2]fmt.Printf("删除文件: %s\n", filename)// 这里可以添加删除文件的逻辑default:fmt.Printf("未知命令: %s\n", command)}
}
2. 用户输入处理
2.1 bufio包的使用
有时候我们需要在程序运行过程中让用户输入一些内容,这时候就要用到bufio
包了。它提供了缓冲读取功能,处理用户输入很方便。
package mainimport ("bufio""fmt""os""strings"
)func main() {// 创建一个从标准输入读取的readerreader := bufio.NewReader(os.Stdin)fmt.Print("请输入你的名字: ")name, err := reader.ReadString('\n') // 读取到换行符为止if err != nil {fmt.Println("读取输入时出错:", err)return}// 去掉末尾的换行符name = strings.TrimSpace(name)fmt.Printf("你好, %s!\n", name)
}
2.2 更实用的输入处理
实际开发中,我们经常需要处理各种类型的输入,比如数字、选择项等:
package mainimport ("bufio""fmt""os""strconv""strings"
)func main() {reader := bufio.NewReader(os.Stdin)// 获取用户年龄fmt.Print("请输入你的年龄: ")ageStr, _ := reader.ReadString('\n')ageStr = strings.TrimSpace(ageStr)age, err := strconv.Atoi(ageStr) // 转换为整数if err != nil {fmt.Println("年龄必须是数字")return}// 根据年龄给出不同回应if age < 18 {fmt.Println("你还是个孩子呢")} else if age < 60 {fmt.Println("正值壮年啊")} else {fmt.Println("人生阅历丰富")}// 让用户选择fmt.Print("你喜欢编程吗?(y/n): ")choice, _ := reader.ReadString('\n')choice = strings.ToLower(strings.TrimSpace(choice))if choice == "y" || choice == "yes" {fmt.Println("太好了!Go语言是个不错的选择")} else {fmt.Println("没关系,每个人都有自己的兴趣")}
}
3. 综合应用实例
3.1 交互式计算器
把命令行参数和用户输入结合起来,我们可以做一个简单的计算器:
package mainimport ("bufio""fmt""os""strconv""strings"
)func main() {// 检查是否有模式参数mode := "interactive" // 默认交互模式if len(os.Args) > 1 {mode = os.Args[1]}switch mode {case "add":if len(os.Args) < 4 {fmt.Println("用法: ./calc add <数字1> <数字2>")return}num1, _ := strconv.ParseFloat(os.Args[2], 64)num2, _ := strconv.ParseFloat(os.Args[3], 64)fmt.Printf("结果: %.2f\n", num1+num2)case "interactive":runInteractiveMode()default:fmt.Println("支持的模式: add, interactive")}
}func runInteractiveMode() {reader := bufio.NewReader(os.Stdin)fmt.Println("=== 简单计算器 ===")fmt.Println("输入 'quit' 退出程序")for {fmt.Print("请输入第一个数字: ")input1, _ := reader.ReadString('\n')input1 = strings.TrimSpace(input1)if input1 == "quit" {fmt.Println("再见!")break}num1, err := strconv.ParseFloat(input1, 64)if err != nil {fmt.Println("请输入有效的数字")continue}fmt.Print("请输入运算符 (+, -, *, /): ")operator, _ := reader.ReadString('\n')operator = strings.TrimSpace(operator)fmt.Print("请输入第二个数字: ")input2, _ := reader.ReadString('\n')input2 = strings.TrimSpace(input2)num2, err := strconv.ParseFloat(input2, 64)if err != nil {fmt.Println("请输入有效的数字")continue}var result float64switch operator {case "+":result = num1 + num2case "-":result = num1 - num2case "*":result = num1 * num2case "/":if num2 == 0 {fmt.Println("除数不能为0")continue}result = num1 / num2default:fmt.Println("不支持的运算符")continue}fmt.Printf("结果: %.2f %s %.2f = %.2f\n\n", num1, operator, num2, result)}
}
4. 编译和使用
4.1 编译程序
Go程序编译很简单,一条命令就搞定:
# 编译当前目录的go文件
go build main.go# 或者指定输出文件名
go build -o mytool main.go
在Windows下会生成.exe
文件,Linux和Mac下是可执行文件。
4.2 运行和测试
编译完成后就可以运行了:
# 不带参数运行
./mytool# 带参数运行
./mytool add 10 20# 交互模式
./mytool interactive
5. 两种输入方式的区别
理解os.Args
和bufio
的区别很重要:
os.Args的特点:
- 程序启动时就确定了,运行过程中不会变
- 适合做程序的配置和模式选择
- 用户必须在启动程序时就提供所有参数
bufio的特点:
- 程序运行时动态获取用户输入
- 可以多次交互,实现对话式程序
- 用户可以根据程序提示逐步输入
实际开发中,这两种方式经常结合使用。用os.Args
确定程序的工作模式,用bufio
在特定模式下与用户交互。
比如git命令就是这样:git commit
确定了要提交代码,如果没有-m
参数,git会打开编辑器让你输入提交信息。
掌握了这两个基础工具,你就可以开始写各种实用的命令行程序了。从简单的文件处理工具到复杂的系统管理脚本,都离不开这些基础知识。