英文:
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解析错误,例如EOF
,unexpected 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>
> The `os.File` or `[]byte` is used in two goroutines at once...
That'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't state explicitly that it'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 "from it", there'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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论