Go读CSV中文乱码因不处理BOM和GBK编码,需手动切BOM或用charmap转码;flag不支持--help需显式定义;输入校验要TrimSpace并转大写;答案列须按header动态定位,题号用独立变量。

读 CSV 文件时中文乱码或字段错位
Go 默认不处理 CSV 的 BOM 和编码转换,直接用 encoding/csv 读取 UTF-8-BOM 或 GBK 编码的文件,大概率会报 invalid UTF-8 错误,或者第一行字段整体偏移(比如标题被吞掉一个字)。
- 先用
os.ReadFile读原始字节,检查开头是否为\xEF\xBB\xBF(UTF-8-BOM),有就切掉再交给csv.NewReader - 如果 CSV 来自 Windows Excel 导出且含中文,大概率是 GBK 编码——Go 标准库不支持,得用
golang.org/x/text/encoding/charmap转成 UTF-8 后再解析 - 别跳过 header 行用
reader.Read()两次,而是用reader.Read()读第一行当headers,后续每行用reader.Read()拿数据,否则容易漏题
用 flag 包解析命令行参数但 --help 不生效
flag 包默认只响应 -h,不认 --help;而且一旦调用 flag.Parse() 后再手动检查 os.Args,就可能重复解析或漏参数。
- 显式注册
helpbool 类型 flag:var help = flag.Bool("help", false, "show usage"),然后在flag.Parse()后立刻判断*help - 避免混用
flag.String和位置参数:比如想支持quiz -f questions.csv和quiz questions.csv两种写法,必须统一用 flag 解析,否则flag.Parse()会把后者当“非 flag 参数”丢进flag.Args(),逻辑容易分裂 - 所有 flag 必须在
main()开头就声明,不能在 if 分支里动态定义,否则flag.Usage不会显示它们
交互式答题时用户输错选项卡住不动
用 fmt.Scanln 或 bufio.Scanner 读用户输入,若用户输了个空行、带空格的字母(如 " A ")、或非预期字符(如 "1" 而不是 "A"),程序常直接 panic 或无限循环。
- 一律用
bufio.NewReader(os.Stdin).ReadString('\n')读整行,再用strings.TrimSpace清空首尾空白,避免空行干扰 - 校验前先转成大写:
strings.ToUpper(input),统一处理a/A/"a " - 别用
switch input直接匹配,而应先检查len(input) == 1 && strings.Contains("ABCD", input),否则用户输"AB"或"X"就静默失败
统计答对题数但总题数和答案索引对不上
CSV 中题目行和答案列的映射关系一旦写死(比如认为第 4 列永远是正确答案),遇到表头顺序变动、空行、或注释行就会错判——尤其从不同来源合并题库时极常见。
立即学习“go语言免费学习笔记(深入)”;
- 务必用第一行 header 做字段定位:读完 header 后查
index := slices.Index(headers, "answer")(Go 1.21+)或手写遍历,之后每行都按 index 取值 - 正确答案列内容应是单个字母(
"A"),不是文字描述;如果 CSV 里存的是"选项一",就得在加载时做映射:map[string]string{"选项一": "A", "选项二": "B"} - 记录当前题号用独立变量(如
qNum := 1),不要依赖循环i——跳过空行或无效行后,i和实际题号就脱节了
最麻烦的其实是 CSV 字段里带换行符或逗号(比如题干含“,”),这时必须确保导出时字段用双引号包裹,且 csv.NewReader 的 FieldsPerRecord 设为 -1,并接受 LazyQuotes: true。没人会提前告诉你 Excel 导出的 CSV 其实不标准。










