Go语言技术与应用(六):命令行工具开发基础

举报
Yeats_Liao 发表于 2025/11/22 21:23:49 2025/11/22
【摘要】 命令行工具在日常开发中用得很多,比如git、docker这些我们天天用的工具。Go语言写命令行程序特别方便,语法简单,编译后就是一个可执行文件,部署起来很轻松。这篇文章会带你从零开始,学会用Go写命令行工具的基础知识。主要涉及两个核心内容:如何处理命令行参数和如何获取用户输入。 1. 命令行参数处理 1.1 os.Args基础用法Go语言内置的os.Args是个字符串切片,专门用来获取命令行...

命令行工具在日常开发中用得很多,比如git、docker这些我们天天用的工具。Go语言写命令行程序特别方便,语法简单,编译后就是一个可执行文件,部署起来很轻松。

这篇文章会带你从零开始,学会用Go写命令行工具的基础知识。主要涉及两个核心内容:如何处理命令行参数和如何获取用户输入。

1. 命令行参数处理

1.1 os.Args基础用法

Go语言内置的os.Args是个字符串切片,专门用来获取命令行参数。它有个特点:第一个元素永远是程序本身的名字,从第二个元素开始才是用户传入的参数。

来看个简单例子:

package main

import (
    "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 main

import (
    "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 main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func main() {
    // 创建一个从标准输入读取的reader
    reader := 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 main

import (
    "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 main

import (
    "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 float64
        switch operator {
        case "+":
            result = num1 + num2
        case "-":
            result = num1 - num2
        case "*":
            result = num1 * num2
        case "/":
            if num2 == 0 {
                fmt.Println("除数不能为0")
                continue
            }
            result = num1 / num2
        default:
            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.Argsbufio的区别很重要:

os.Args的特点:

  • 程序启动时就确定了,运行过程中不会变
  • 适合做程序的配置和模式选择
  • 用户必须在启动程序时就提供所有参数

bufio的特点:

  • 程序运行时动态获取用户输入
  • 可以多次交互,实现对话式程序
  • 用户可以根据程序提示逐步输入

实际开发中,这两种方式经常结合使用。用os.Args确定程序的工作模式,用bufio在特定模式下与用户交互。

比如git命令就是这样:git commit确定了要提交代码,如果没有-m参数,git会打开编辑器让你输入提交信息。

掌握了这两个基础工具,你就可以开始写各种实用的命令行程序了。从简单的文件处理工具到复杂的系统管理脚本,都离不开这些基础知识。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。