You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言Learntris挑战:Scanner读取stdin遇空数组问题求助

解决Go中Scanner读取Learntris网格内容为空的问题

我之前做Learntris入门项目的时候也踩过这个Scanner的坑!你遇到的空数组问题,大概率是Scanner的换行符处理或者分割模式用错了,尤其是单字符命令和多行内容衔接的地方容易出问题。

先给你拆解下常见的错误原因和对应的解决办法:

最可能的问题:错误使用了字符分割模式

很多人为了读取单个字符命令,会把Scanner的分割方式改成bufio.ScanRunes,但这样会把换行符也当作一个独立的字符来读取。比如输入是:

g
line1
line2
...

当你用ScanRunes读取到'g'后,下一次Scan()会读取到换行符(\n),这时候你开始循环读22行,第一行就会是空字符串,后续如果输入不足22行,还会出现更多空元素,最终看起来像是得到了空数组。

解决办法:放弃ScanRunes,用Scanner默认的ScanLines分割模式(也就是不修改Split)。因为Learntris的输入本来就是换行分隔的,每个命令单独占一行,'g'命令本身就是一行完整的输入,直接读取整行判断是否为"g"就可以了。

正确的代码实现示例

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// 循环处理每行命令
	for scanner.Scan() {
		cmd := scanner.Text()
		switch cmd {
		case "g":
			grid := make([]string, 0, 22)
			// 读取22行网格内容
			for i := 0; i < 22; i++ {
				// 必须检查Scan的返回值,避免EOF或IO错误导致空内容
				if !scanner.Scan() {
					fmt.Printf("警告:网格内容不足22行,仅读取到%d行\n", len(grid))
					break
				}
				grid = append(grid, scanner.Text())
			}
			// 验证读取结果
			fmt.Printf("成功读取%d行网格内容:\n", len(grid))
			for idx, line := range grid {
				fmt.Printf("%d: %s\n", idx+1, line)
			}
		// 处理其他命令,比如'q'退出之类的
		case "q":
			fmt.Println("退出程序")
			return
		default:
			fmt.Printf("未知命令:%s\n", cmd)
		}
	}

	// 处理Scanner的错误
	if err := scanner.Err(); err != nil {
		fmt.Fprintf(os.Stderr, "读取输入时出错:%v\n", err)
	}
}

关键注意点

  • 必须检查Scan()的返回值:如果Scan()返回false,说明已经到达EOF或者发生了IO错误,这时候Text()会返回空字符串,一定要提前处理,避免把空值塞进数组。
  • 不要手动处理换行符:默认的ScanLines会自动去掉每行末尾的换行符(包括\n和\r\n),直接用Text()就能得到干净的行内容。
  • 提前预分配数组容量:用make([]string, 0, 22)可以避免数组扩容的性能损耗,虽然对于22行来说影响不大,但这是Go的最佳实践。

如果你之前确实用了ScanRunes,也可以在读取到'g'后,额外调用一次Scan()来跳过换行符,再读取22行,但这种方式不如默认的行分割模式直观,容易踩坑,所以更推荐用上面的方法。

内容的提问来源于stack exchange,提问作者paumanok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:02:43