Why does json.Unmarshal work with reference but not pointer?

前端 未结 4 1986
不思量自难忘°
不思量自难忘° 2020-12-24 10:58

This example from the json.Unmarshal docs (slightly modified for simplicity to use Animal instead of []Animal) works, no errors:

Playground

相关标签:
4条回答
  • 2020-12-24 11:32

    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

    In your case, json.Unmarshal accept interface as second argument

    0 讨论(0)
  • 2020-12-24 11:36

    I believe the issue is that, while you can pass a pointer to nil to Unmarshal(), you can't pass a nil pointer value.

    A pointer to nil would be like:

    var v interface{}
    json.Unmarshal(text, &v)
    

    The value of v is nil, but the pointer to v is 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.

    A nil pointer would be like:

    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 v is the type's zero-value. So v is a zero-value pointer, which means it isn't pointing to any valid place in memory.

    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.

    0 讨论(0)
  • 2020-12-24 11:37

    Because your pointer is nil.

    If you initialize it it works: 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)

    0 讨论(0)
  • 2020-12-24 11:43

    You've encountered an InvalidUnmarshalError (see lines 109 and 110 in decode.go).

    // An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
    // (The argument to Unmarshal must be a non-nil pointer.)

    It seems the docs could do with some clarification as the quote above and the comment below from the Unmarshal source seem to contradict each other.

    If the pointer is nil, Unmarshal allocates a new value for it to point to.

    0 讨论(0)
提交回复
热议问题