Go中rand.Intn()默认种子固定致结果恒为0,需调用rand.Seed()或使用rand.New();生成[1,100]应写rand.Intn(100)+1;输入非数字时须检查scanf错误并清空缓冲区;猜数字宜用for{}+break而非for条件判断。

Go 里 rand.Intn() 总是返回 0?没调 rand.Seed() 就别怪它不随机
Go 1.20 之后 rand.Intn() 默认用的是全局伪随机源,但它的种子默认是固定值(比如 1),所以每次运行程序,生成的“随机数”序列完全一样。这不是 bug,是设计——但新手常以为自己写错了逻辑。
- 必须手动调用
rand.Seed(time.Now().UnixNano())才能获得真随机起点(注意:Go 1.20+ 推荐用rand.New(rand.NewSource(...))实例化独立源,避免全局污染) - 如果只在 main 开头调一次
rand.Seed(),后续所有rand.Intn()调用才真正“变起来” - 常见错误:在 for 循环里反复调
rand.Seed(),尤其用time.Now(),可能因纳秒时间相同导致连续几次种子一样,反而更不随机
猜数字游戏里怎么生成 [1, 100] 的整数?别直接 rand.Intn(100)
rand.Intn(n) 返回的是 [0, n) 区间,即 0 到 99(含)。想要 1 到 100(含),得手动偏移:加 1。
- 正确写法:
rand.Intn(100) + 1→ 范围 [1, 100] - 错误写法:
rand.Intn(101)看似“多一个”,但会得到 [0, 101),即 0~100,包含 0 和 100,不符合“1~100”的业务要求 - 如果范围可配置,建议封装成函数:
randomInt(min, max int) int { return rand.Intn(max-min+1) + min },避免每次手算边界
用户输入不是数字时,fmt.Scanf() 卡住或读错?别让它吃掉换行符
用 fmt.Scanf("%d", &guess) 读整数时,如果用户输的是 "abc",scanf 会失败、返回错误,并把非法输入留在缓冲区——下次再读,还是那个 "abc",形成死循环。
- 必须检查
fmt.Scanf()的第二个返回值:_, err := fmt.Scanf("%d", &guess),err != nil就说明输入非法 - 出错后要清空输入缓冲区,否则下一轮还卡着。简单做法:
bufio.NewReader(os.Stdin).ReadBytes('\n') - 更稳妥的做法是用
bufio.Scanner先读整行字符串,再用strconv.Atoi()转换,这样可控性更强,也方便提示“请输入数字”
为什么用 for {} 死循环 + break 比 for condition 更适合猜数字?
因为终止条件不是单个布尔表达式能概括的:既要判断数字是否相等,又要处理输入错误、范围越界、主动退出等多种分支。硬塞进 for guess != answer 会导致逻辑割裂、错误处理被忽略。
立即学习“go语言免费学习笔记(深入)”;
- 用
for {}+ 多个if分支 +break,每种情况(猜中、太大、太小、输入错、超限)都能独立响应,结构更平铺直叙 - 如果强行用
for guess != answer && validInput,validInput 变量需要在每次迭代开头重置,容易漏设,反而增加心智负担 - 性能无差异,Go 的
break是零开销跳转,不用顾虑“不优雅”之类说法
最麻烦的其实是输入校验和缓冲区清理——这两块代码看着少,漏掉一个,整个游戏就卡在终端里动不了。写完先故意输几次字母,确认它不会挂住,再算过关。











