
本文详解 go 程序中获取和解析命令行参数的正确方法,重点解决因误用 `strconv.parseint` 基数参数导致的零值错误、错误忽略及参数长度校验缺失等常见问题。
在 Go 中,命令行参数通过 os.Args 切片暴露:os.Args[0] 是程序执行路径(如 ./prime),后续元素才是用户传入的参数(os.Args[1], os.Args[2], …)。初学者常犯的错误包括:忽略参数数量校验、丢弃解析错误、误设数值进制(base)——这正是提问代码输出 0 is a composite... 的根本原因。
关键问题在于这一行:
n, _ = strconv.ParseInt(os.Args[1], 64, 64)
strconv.ParseInt 的第二个参数是进制(base),合法范围为 2–36(例如 10 表示十进制,16 表示十六进制)。传入 64 属于非法值,函数立即返回错误,而 _ 忽略了该错误,导致 n 保持其零值 0,后续逻辑自然失效。
✅ 正确写法应为:
n, err := strconv.ParseInt(os.Args[1], 10, 64) // 十进制解析 int64
if err != nil {
fmt.Fprintf(os.Stderr, "error: invalid number '%s': %v\n", os.Args[1], err)
os.Exit(1)
}同时,参数数量检查也需修正。原代码 if len(os.Args) > 1 仅确保存在 os.Args[1],但未验证 os.Args[2](certainty)是否存在。正确逻辑是:
if len(os.Args) < 3 {
fmt.Fprintf(os.Stderr, "usage: %s \n", os.Args[0])
os.Exit(1)
} 完整修复后的 main 函数示例如下:
func main() {
if len(os.Args) < 3 {
fmt.Fprintf(os.Stderr, "usage: %s \n", os.Args[0])
os.Exit(1)
}
n, err := strconv.ParseInt(os.Args[1], 10, 64)
if err != nil {
fmt.Fprintf(os.Stderr, "error: invalid number '%s': %v\n", os.Args[1], err)
os.Exit(1)
}
certainty, err := strconv.Atoi(os.Args[2])
if err != nil {
fmt.Fprintf(os.Stderr, "error: invalid certainty '%s': %v\n", os.Args[2], err)
os.Exit(1)
}
isPrime, probability := prime_test(n, certainty)
if isPrime {
fmt.Printf("%d is probably %.8f%% prime.\n", n, probability*100)
} else {
factor := why_not_prime(n)
fmt.Printf("%d is composite (divisible by %d).\n", n, factor)
}
} ? 最佳实践总结:
- ✅ 始终校验 os.Args 长度,确保所需参数存在;
- ✅ 使用 strconv.ParseInt(s, 10, 64) 解析十进制整数,base=10 不可省略或错写;
- ✅ 绝不忽略错误(no _):错误是程序健壮性的第一道防线;
- ✅ 向 os.Stderr 输出错误信息,并调用 os.Exit(1) 明确失败;
- ✅ 对用户友好:提供清晰的 usage 提示。
进阶建议:对于复杂 CLI 应用,推荐使用成熟库如 github.com/spf13/cobra 或标准库 flag 包,它们自动处理类型转换、帮助生成与参数验证,大幅提升开发效率与可靠性。








