Just started with Go and I have a small doubt from a tutorial I am following. I read that Unmarshall
is some kind of JSON encoding, my doubt here is: err = json.Unmarshal(body, &p)
why are we assigning the encoded body to err
and how is p.Stuff.Fruit
getting the value when I can't see anything assigned to p
.
Note : produce is different package which contains some type and arrays.*
func main() {
url := "http://localhost:12337"
res, err := http.Get(url)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
var p produce.Payload
err = json.Unmarshal(body, &p) // I cant get this
if err != nil {
panic(err)
}
// how are these getting the values assigned to them
fmt.Println(p.Stuff.Fruit)
fmt.Println(p.Stuff.Veggies)
}
my doubt here is:
err = json.Unmarshal(body, &p)
why are we assigning the encoded body toerr
You don't. You pass the body
to the json.Unmarshal()
function, and you assign its return value to the err
variable, which tells you if unmarshaling failed (or succeeded if err
is nil
).
how is
p.Stuff.Fruit
getting the value when I can't see anything assigned top
You pass the address of p
to json.Unmarshal()
, so it has a pointer to your variable, and so if it modifies the pointed value (pointed by the pointer), it modifies the same value you have (p
).
See this simple example:
func change(p *int) {
*p = 3
}
func main() {
var i int
fmt.Println("Before", i)
change(&i)
fmt.Println("After", i)
}
Output (try it on the Go Playground):
Before 0
After 3
In the main()
function we don't assign anything to the local variable i
, but we pass its address to the change()
function, which modifies the pointed value, and so if we print the value of i
after the change()
call, we see its value changed.
You pass the address of p
to json.Unmarshal()
, so it will be capable of modifying the value stored in p
. Under the hood, the json
package uses reflection (package reflect
) to discover the runtime type of p
and modify it according to the JSON document you pass to it to parse.
You have created a pointer to payload using &p
address operator. Now It saves the value at an address pointed by p. According to Golang spec Unmarshal takes data in bytes format and interface{} to wrap the variable storing the data at an address.
Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.
Unmarshal function returns an error
func Unmarshal(data []byte, v interface{}) error
var m Message
err := json.Unmarshal(b, &m)
which is why it is assigned to a variable. You can surpass it using _
operator but it is not a good approach
_ := json.Unmarshal(b, &m)