flag.parse()必须在所有flag.*定义之后调用,否则后续flag不会被解析;短选项需手动注册;位置参数用flag.args()获取;自定义类型需实现flag.value接口。
flag.Parse() 必须在所有 flag.* 定义之后调用
很多新手写完 flag.String 或 flag.Int 就直接调用 flag.Parse(),结果发现参数始终是默认值。根本原因是:flag 在定义时只是注册变量,真正赋值发生在 flag.Parse() 执行时,且它只读取已注册的 flag。如果 flag.Parse() 调用太早(比如在定义前或中间),后续定义的 flag 根本不会被解析。
正确顺序必须是:
- 所有
flag.String/flag.Bool/flag.Int等定义完成 - 然后才调用
flag.Parse() - 最后访问变量值
示例错例:
port := flag.Int("port", 8080, "server port")
flag.Parse() // ❌ 太早 —— 此时其他 flag 还没定义
name := flag.String("name", "", "user name") // 这个永远不会被解析
短选项(-h)和长选项(–help)要手动支持
flag 包默认不提供 -h 短选项别名,flag.Bool("help", false, "...") 只响应 --help。如果你希望同时支持 -h 和 --help,得自己注册两个 flag 并共享同一个变量:
- 用指针共享存储:
help := flag.Bool("help", false, "show help"),再加flag.BoolVar(help, "h", false, "show help") - 或者更常见的是:用
flag.BoolVar绑定已有变量,避免重复声明 - 注意:两个 flag 的 usage 文本最好一致,否则
flag.PrintDefaults()会打印两遍
不这么做的话,用户输 ./cmd -h 会报错 flag provided but not defined: -h。