json.unmarshal读取文件前必须先用os.readfile获取字节流,因其只接受[]byte;传入路径字符串会导致panic;勿用bufio.scanner逐行读,json非行格式。

用 json.Unmarshal 读取文件内容前必须先读到字节流
Go 没有直接“从文件路径解析 JSON”的函数,json.Unmarshal 只接受 []byte。常见错误是传入文件指针或字符串路径,结果 panic:invalid character 'p' looking for beginning of value(其实是把文件路径字符串当 JSON 内容了)。
正确做法分两步:先用 os.ReadFile 拿到原始字节,再交给 json.Unmarshal。别用 bufio.Scanner 或逐行读——JSON 不是行格式,换行缩进不影响结构,但手动拼接容易丢数据。
-
os.ReadFile("config.json")最简,适合小文件(os.Open +io.ReadAll控制内存 - 如果 JSON 文件带 UTF-8 BOM,
json.Unmarshal会报错invalid character '\ufeff',需提前切掉:bytes.TrimPrefix(data, []byte("\xef\xbb\xbf")) - 注意文件权限和路径:相对路径以
os.Executable所在目录为基准,不是go run当前目录
结构体字段必须导出且加 json tag 才能反序列化
Go 的 JSON 解析依赖反射,只能设置导出字段(首字母大写)。没加 json tag 时,字段名必须和 JSON key 完全一致(大小写敏感);加了 tag 才能映射别名、忽略字段或处理大小写不匹配。
典型翻车现场:{"user_name": "alice"} 对应结构体字段写成 UserName string 却没加 json:"user_name",结果值为空字符串。
- 嵌套对象字段也要导出,否则整层被跳过
- 用
json:",omitempty"可跳过零值字段,但要注意:指针 nil、空 slice、空 map 都算零值 - 数字字段若用
int接收浮点型 JSON 数字(如42.0),会报错json: cannot unmarshal number into Go struct field;统一用float64更稳妥
遇到 json: unknown field 别急着删字段
这个错误不是 JSON 格式错,而是结构体里没定义对应字段。默认情况下,json.Unmarshal 对多出来的 key 是严格拒绝的。但很多配置文件会逐步加字段,老代码不能每次改结构体。
两种实用解法:
- 加
json.RawMessage字段兜底,比如Extra json.RawMessage,后续按需解析 - 用
Decoder.DisallowUnknownFields()显式关闭校验(Go 1.19+):dec := json.NewDecoder(f) dec.DisallowUnknownFields() // 不加这行就默认容忍未知字段
- 注意:关闭校验后,拼写错误的字段名也不会报错,调试时更难发现 typo
大 JSON 文件别硬塞进内存
几百 MB 的日志 JSON 数组(如 [{...},{...},...])用 json.Unmarshal 会 OOM。得用流式解析:json.Decoder 配合 Decode 循环读。
关键点:数组外层必须是合法 JSON,Decoder 能自动跳过空白和换行,但不能跳过多个顶层值(如 {"a":1}{"b":2} 不合法)。
- 对 JSON 数组,先
dec.Token()检查是否为[,再循环dec.Decode(&item) - 每个
item用独立结构体或map[string]interface{},避免复用变量导致数据覆盖 - 流式解析不校验整个文件合法性,某条记录坏掉只会中断当前 Decode,可 recover 继续下一条
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











