json.Unmarshal()如何工作以及如何存储在变量中?

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 to err

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 to p

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)