Go 入门(15):命令行参数——flag 包解析参数
更新时间:2026-09-01。本文是
languages/go/beginner/入门层第 15 篇,接 文件 I/O。写 CLI 工具需要解析命令行参数,Go 标准库flag包支持基础解析,简单需求不用第三方库。
本文要回答的问题
os.Args和flag包有什么区别?什么时候用哪个?flag.String和flag.StringVar怎么写?flag.Parse()什么时候调用?调用后os.Args是什么?- 怎么定义布尔参数?
-bool-flag和-bool-flag true一样吗?
一、os.Args:原始参数
如果你只需要取位置参数,直接用 os.Args:
go
package main
import (
"fmt"
"os"
)
func main() {
// os.Args[0] 是程序名,os.Args[1...] 是参数
fmt.Println("程序名:", os.Args[0])
if len(os.Args) > 1 {
fmt.Println("参数:", os.Args[1:])
}
}运行:
bash
./program hello world
// 程序名: ./program
// 参数: [hello world]适合非常简单的脚本,不用解析选项。复杂解析用 flag 包。
二、flag 包:解析选项
基本用法:
go
package main
import "flag"
// 定义选项,返回指针
name := flag.String("name", "default", "your name")
age := flag.Int("age", 18, "your age")
isVip := flag.Bool("vip", false, "is vip")
// 解析命令行参数
flag.Parse()
fmt.Println(*name)
fmt.Println(*age)
fmt.Println(*isVip)运行:
bash
./program -name Alice -age 25 -vip
// Alice 25 true三、另一种写法:存到变量
如果不想用指针,用 flag.XxxVar:
go
var name string
var age int
var isVip bool
flag.StringVar(&name, "name", "default", "your name")
flag.IntVar(&age, "age", 18, "your age")
flag.BoolVar(&isVip, "vip", false, "is vip")
flag.Parse()
// 直接用 name、age、isVip,不用解引用四、布尔参数的注意点
Go 布尔参数默认有值标志:
-debug→true-debug=true→true-debug=false→false
所以 flag.Bool("debug", false) 就是默认 false,命令行写 -debug 就变成 true,不用写 -debug=true。
五、解析后的位置参数
flag.Parse() 之后,flag.Args() 是解析后剩下的位置参数(不是选项部分):
go
// 定义选项
name := flag.String("name", "", "name")
flag.Parse()
// 拿到剩下的位置参数
args := flag.Args() // []string{...}比如:
bash
./program -name Alice file1.txt file2.txt
// name = "Alice"
// args = ["file1.txt", "file2.txt"]六、完整示例:CLI 工具
go
package main
import (
"flag"
"fmt"
"log"
)
func main() {
name := flag.String("name", "world", "who to greet")
count := flag.Int("count", 1, "how many times")
upper := flag.Bool("upper", false, "uppercase")
flag.Parse()
msg := fmt.Sprintf("Hello, %s!", *name)
if *upper {
msg = strings.ToUpper(msg)
}
for i := 0; i < *count; i++ {
fmt.Println(msg)
}
}运行:
bash
./greet -name Go -count 3 -upper
HELLO, GO!
HELLO, GO!
HELLO, GO!七、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
忘记调用 flag.Parse() | 参数都是默认值 | 定义完 flag 后必须 flag.Parse() |
| 用指针不 dereference | 打印出来是地址不是值 | *name 才能取到值,或者用 flag.XxxVar |
| 位置参数在选项前面 | -name 解析错误 | 选项放前面,位置参数放后面 |
| 需要更复杂解析 | flag 不够用 | 用第三方库 github.com/spf13/cobra |
相关与延伸
下一篇:错误处理进阶——fmt.Errorf 与 errors 包;复杂 CLI 工具推荐用 Cobra,进阶讲 Go 第三方包管理;flag 的底层解析,不需要你深入,直接用就行。
一句话总结
Go 命令行参数:简单脚本直接用 os.Args;需要解析选项用 flag 包,flag.String 返回指针,flag.StringVar 存到现有变量;布尔参数写 -bool 就是 true;flag.Parse() 之后 flag.Args() 拿剩下的位置参数;复杂需求直接上 cobra,别在 flag 里硬造轮子。