为什么 json.Unmarshal 使用引用而不是指针?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20478577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does json.Unmarshal work with reference but not pointer?
提问by Matt
This example from the json.Unmarshaldocs (slightly modified for simplicity to use Animalinstead of []Animal) works, no errors:
这个来自json.Unmarshal文档的例子(为了简单使用Animal而不是稍微修改[]Animal)有效,没有错误:
Playground link of working example
// ...
var animals Animal
err := json.Unmarshal(jsonBlob, &animals)
// ...
But this slightly modified example doesn't:
但是这个稍微修改的例子没有:
Playground link of non-working example
// ...
var animals *Animal
err := json.Unmarshal(jsonBlob, animals)
// ...
It displays this obscure error that really isn't helpful (looks more like a function call than an error IMO):
它显示了这个确实没有帮助的模糊错误(看起来更像是函数调用而不是错误 IMO):
json: Unmarshal(nil *main.Animal)
json: Unmarshal(nil *main.Animal)
This appears to be because animalsis an uninitialized pointer. But the docs say (emphasis mine):
这似乎是因为animals是一个未初始化的指针。但是文档说(强调我的):
Unmarshal unmarshals the JSON into the value pointed at by the pointer. If the pointer is nil, Unmarshal allocates a new value for it to point to.
Unmarshal 将 JSON 解组为指针指向的值。如果指针为 nil,则 Unmarshal 为其分配一个新值以指向它。
So why does unmarshaling fail in the second example and show that obscure error?
那么为什么在第二个示例中解组失败并显示出那个晦涩的错误呢?
(Also, is it "unmarshalling" or "unmarshaling" (one L)? The docs use both.)
(此外,它是“解组”还是“解组”(一个 L)?文档同时使用了两者。)
采纳答案by Intermernet
You've encountered an InvalidUnmarshalError(see lines 109 and 110 in decode.go).
您遇到了InvalidUnmarshalError(请参阅decode.go 中的第 109 和 110 行)。
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
// (The argument to Unmarshal must be a non-nil pointer.)
// InvalidUnmarshalError 描述了传递给 Unmarshal 的无效参数。
// (Unmarshal 的参数必须是非 nil 指针。)
It seems the docs could do with some clarification as the quote above and the comment below from the Unmarshalsourceseem to contradict each other.
似乎文档可以做一些澄清,因为上面的引用和下面来自Unmarshal来源的评论似乎相互矛盾。
If the pointer is nil, Unmarshal allocates a new value for it to point to.
如果指针为 nil,则 Unmarshal 为其分配一个新值以指向它。
回答by Eve Freeman
Because your pointer is nil.
因为你的指针为零。
If you initialize it it works: http://play.golang.org/p/zprmV0O1fG
如果你初始化它就可以工作:http: //play.golang.org/p/zprmV0O1fG
var animals *Animal = &Animal{}
Also, it can be spelled either way (consistency in a single doc would be nice, though): http://en.wikipedia.org/wiki/Marshalling_(computer_science)
此外,它可以用任何一种方式拼写(不过,单个文档的一致性会很好):http: //en.wikipedia.org/wiki/Marshalling_(computer_science)
回答by Russ Egan
I believe the issue is that, while you can pass a pointer to nilto Unmarshal(), you can't pass a nil pointer value.
我相信问题在于,虽然您可以将指向 nil的指针传递给 Unmarshal(),但您不能传递nil 指针 value。
A pointer to nil would be like:
指向 nil 的指针类似于:
var v interface{}
json.Unmarshal(text, &v)
The value of vis nil, but the pointer to vis a non-zero pointer address. It's a non-zero pointer, which is pointing to a nil interface{} (which itself is a pointer type). Unmarshal doesn't return an error in this case.
的值为vnil,但指向的指针v是非零指针地址。它是一个非零指针,指向一个 nil interface{}(它本身是一个指针类型)。在这种情况下,解组不会返回错误。
A nil pointer would be like:
一个 nil 指针是这样的:
var v *interface{}
json.Unmarshal(text, v)
In this case, the type of v is pointer to an interface{}, but as with any declaration of a var in golang, the initial value of vis the type's zero-value. So vis a zero-value pointer, which means it isn't pointing to any valid place in memory.
在这种情况下, v 的类型是pointer to an interface{},但与 golang 中 var 的任何声明一样, 的初始值v是该类型的零值。所以v是一个零值指针,这意味着它不指向内存中任何有效的地方。
As mentioned in the https://stackoverflow.com/a/20478917/387176, json.Unmarshal() needs a valid pointer to something, so it can change the something (be it a zero value struct, or a pointer) in place.
正如在https://stackoverflow.com/a/20478917/387176 中提到的, json.Unmarshal() 需要一个指向something的有效指针,所以它可以改变某些东西(无论是零值结构还是指针)就地.
回答by user3107237
I had a similiar condition before but in a different case. It is related with concept of interface in Go. If a function declares a interface as argument or return value, the caller have to pass or return the reference
我以前有过类似的情况,但在不同的情况下。它与 Go 中的接口概念有关。如果函数将接口声明为参数或返回值,则调用者必须传递或返回引用
In your case, json.Unmarshalaccept interface as second argument
在您的情况下,json.Unmarshal接受接口作为第二个参数

