
本教程详解 go 程序如何正确读取并统计标准输入(stdin)中重复行的出现频次,解决因未正确终止输入导致程序“卡住”的常见问题。
本教程详解 go 程序如何正确读取并统计标准输入(stdin)中重复行的出现频次,解决因未正确终止输入导致程序“卡住”的常见问题。
Go 的 bufio.Scanner 默认以换行符为分隔符逐行读取 stdin,但它不会因用户按下 Enter 就自动结束循环——程序会持续等待更多输入,直到遇到 EOF(文件结束符)。这就是你“按下回车无反馈”的根本原因:input.Scan() 仍在阻塞等待后续输入,循环尚未退出,自然无法执行后续的统计输出逻辑。
✅ 正确做法是显式触发 EOF:
- Linux/macOS 终端:输入完毕后按 Ctrl+D(Unix EOF 字符);
- Windows 终端:按 Ctrl+Z 后回车;
- 更可靠的方式(推荐):将输入数据存为文件,通过管道传入,避免交互式输入的不确定性。
以下为优化后的完整示例(含错误处理与清晰提示):
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]int
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("请输入文本(每行一条,输入完成后按 Ctrl+D(macOS/Linux)或 Ctrl+Z(Windows)结束):")
// 安全读取,检查扫描错误
for scanner.Scan() {
line := scanner.Text()
counts[line]++
}
if err := scanner.Err(); err != nil {
fmt.Fprintf(os.Stderr, "读取输入时出错: %v\n", err)
os.Exit(1)
}
// 输出出现次数 ≥2 的行(按字典序可选排序,此处省略以保持简洁)
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}? 关键注意事项:
- scanner.Scan() 返回 false 仅当遇到 EOF 或错误,单纯回车只会生成空行并继续循环;
- 始终检查 scanner.Err(),避免忽略 I/O 错误;
- 生产环境建议添加超时控制或最大行数限制,防止恶意长输入;
- 若需实时响应(如边输入边统计),应改用 bufio.NewReader + 手动解析,但会增加复杂度。
通过理解 EOF 机制并采用管道测试(如 cat input.txt | go run main.go),即可稳定、可复现地验证行计数逻辑。

















