Go读取JSON文件需先os.Open打开文件并用io.ReadAll读取字节流,再json.Unmarshal解析;结构体字段须首字母大写且正确使用json tag;大文件推荐json.Decoder流式解析。

Go 读取 JSON 文件的核心是 os.Open + json.Unmarshal,但直接用 json.Unmarshal 解析文件内容前必须先读取字节流;常见错误是忽略错误检查、结构体字段未导出、或类型不匹配导致静默失败。
如何正确打开并读取 JSON 文件内容
Go 没有“直接解析文件”的 JSON 函数,必须手动读取文件为 []byte 后再解析。跳过这一步(比如误以为 json.NewDecoder 能自动打开路径)会导致 panic 或空数据。
-
os.Open打开文件,返回*os.File;记得用defer f.Close() - 推荐用
io.ReadAll(f)(Go 1.16+)读取全部内容;旧版本可用io/ioutil.ReadFile(已弃用,但仍可用) - 务必检查
os.Open和读取过程的 error,空文件或权限问题会在这里暴露
结构体定义与 JSON 字段映射的关键规则
JSON 解析失败却无报错?大概率是结构体字段不可导出(首字母小写),或 tag 写错。Go 的 json 包只处理导出字段,且默认按字段名匹配(区分大小写)。
- 结构体字段名必须首字母大写,例如
Name,不能是name - 用
json:"name"tag 显式指定键名,支持别名、省略(json:"-")、可选(json:",omitempty") - 嵌套 JSON 对象需对应嵌套结构体或
map[string]interface{},后者灵活但失去类型安全
用 json.Decoder 流式解析大文件
当 JSON 文件很大(如超过几十 MB),一次性读入内存可能 OOM。json.Decoder 支持从 io.Reader(包括 *os.File)边读边解析,适合数组型 JSON 或单对象场景。
- 对顶层是 JSON 数组的文件,需配合循环调用
Decode;注意 EOF 判断(err == io.EOF是正常结束) - 若文件是单个对象,
Decode调用一次即可;多次调用会报invalid character - 相比
Unmarshal,Decoder更省内存,但无法回退或随机访问
file, err := os.Open("config.json")
if err != nil {
log.Fatal(err)
}
defer file.Close()
var cfg struct {
Port int `json:"port"`
Host string `json:"host"`
}
if err := json.NewDecoder(file).Decode(&cfg); err != nil {
log.Fatal(err)
}
fmt.Printf("Port: %d, Host: %s\n", cfg.Port, cfg.Host)
最容易被忽略的是:JSON 中数字字段如果实际是字符串(如 "port": "8080"),而结构体定义为 int,json 包默认不自动转换——会报 cannot unmarshal string into Go struct field。这种类型不一致必须提前约定或加中间转换层。










