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

json.Unmarshal可解析文件数据,json.NewDecoder.Decode为何失败?

两种JSON反序列化方式报错的原因分析

现象对比

  • 以下代码可正常完成结构体反序列化:
func foo() {
  d, err := os.ReadFile("file.json")

  var t T
  if err := json.Unmarshal(d, &t); err != nil {
    panic(err)
  }
}
  • 但以下代码会抛出EOF、unexpected token 't'等JSON解析错误:
func foo() {
  f, err := os.Open("file.json")
  
  var t T
  if err := json.NewDecoder(f).Decode(&t); err != nil {
    panic(err)
  }
}

核心原因(结合多goroutine场景)

问题出在两种方式对数据源的处理特性差异,以及你提到的「os.File或[]byte被同时用于两个goroutine」的场景:

  1. os.ReadFile是一次性将整个文件内容读取到内存的[]byte切片中,后续就算多个goroutine共享这个切片,只要不对切片做修改,每个goroutine拿到的都是完整、独立的JSON内容副本,json.Unmarshal可以基于完整数据正常解析。
  2. os.Open返回的os.File是一个带读取偏移量的有状态句柄,文件的读取位置会随着每次读操作自动移动。如果多个goroutine同时使用同一个os.File实例(比如各自创建Decoder去Decode),会导致文件指针的偏移被多goroutine的读操作打乱:A goroutine读了一部分内容后指针移到中间,B goroutine接着读时只能拿到从中间开始的截断JSON片段,自然会触发EOF、非法token这类解析错误。

补充:你提供的JSON结构(包含data数组的对象)本身没有语法问题(第一种方式能正常解析也佐证了这一点),所以报错和JSON结构无关,完全是多goroutine共享有状态文件句柄导致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:56:50