json.Unmarshal函数可以正常工作,但json.NewDecoder().Decode()函数无法正常工作。

huangapple go评论87阅读模式
英文:

json.Unmarshal file data works but json.NewDecoder().Decode() does not

问题

以下是翻译好的内容:

以下代码正确地反序列化了结构体:

func foo() {
  d, err := os.ReadFile("file.json")

  var t T
  if err := json.Unmarshal(d, &t); err != nil {
    panic(err)
  }
}

但是下面的代码不起作用,并抛出一系列经典的JSON解析错误,例如EOFunexpected token 't'等等。

func foo() {
  f, err := os.Open("file.json")
  
  var t T
  if err := json.NewDecoder(f).Decode(&t); err != nil {
    panic(err)
  }
}

有任何想法为什么会这样?os.File[]byte在两个goroutine中同时使用,并且JSON的结构如下(省略了一些字段):

{
  "data": [
    {
      "field": "stuff",
      "num": 123
    },
    ...
  ]
}
英文:

The following correctly unmarshals the struct:

func foo() {
  d, err := os.ReadFile("file.json")

  var t T
  if err := json.Unmarshal(d, &t); err != nil {
    panic(err)
  }
}

but this doesn't work and throws a bunch of a classic JSON parsing errors i.e. EOF, unexpected token 't', etc.

func foo() {
  f, err := os.Open("file.json")
  
  var t T
  if err := json.NewDecoder(f).Decode(&t); err != nil {
    panic(err)
  }
}

Any idea why? The os.File or []byte is used in two goroutines at once, and the JSON is of the following structure (with some fields omitted):

{
  "data": [
    {
      "field": "stuff",
      "num": 123,
    },
    ...
  ]
}

</details>


# 答案1
**得分**: 3

`os.File`或`[]byte`在两个goroutine中同时使用...这就是问题所在。`os.File`有一个内部文件指针,用于指示下一次读取的位置。如果两个不相关的实体同时从中读取,它们很可能不会读取重叠的数据。第一个实体读取的字节不会被第二个实体重复读取。

此外,`os.File`不适用于并发使用(文档没有明确说明它是安全的):从多个并发的goroutine调用其方法可能导致数据竞争。

当你将`[]byte`传递给多个读取它的函数/ goroutine时,没有共享的指针或索引变量。每个函数/ goroutine都会单独维护自己的索引,并且从多个goroutine中读取一个变量是可以的(在这种情况下,这将是切片头部和切片元素的字段)。

<details>
<summary>英文:</summary>

&gt; The `os.File` or `[]byte` is used in two goroutines at once...

That&#39;s the issue. `os.File` has an internal file pointer, a position where the next read happens. If 2 unrelated entities keep reading from it, they will likely not read overlapping data. Bytes read by the first entity will not be repeated for the second.

Also, `os.File` is not safe for concurrent use (the documentation doesn&#39;t state explicitly that it&#39;s safe): calling its methods from multiple, concurrent goroutines may result in a data race.

When you pass a `[]byte` to multiple functions / goroutines which read &quot;from it&quot;, there&#39;s no shared pointer or index variable. Each function / goroutine will maintain its index, separately, and reading a variable from multiple goroutines is OK (which in this case would be the (fields of the) slice header and the slice elements).

</details>



huangapple
  • 本文由 发表于 2023年2月7日 03:50:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75365929.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定