代码之家  ›  专栏  ›  技术社区  ›  sac Dahal

json是如何实现的。Unmarshal()工作,它是如何存储在变量中的?

  •  -2
  • sac Dahal  · 技术社区  · 7 年前

    刚开始学习Go,我对下面的教程有点怀疑。我读到了 Unmarshall 是某种JSON编码,我的疑问是: err = json.Unmarshal(body, &p) 为什么我们要将编码体指定给 err 怎么样 p.Stuff.Fruit 当我看不到分配给的任何内容时获取值 p .

    注意:product是不同的包,它包含一些类型和数组*

    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)
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   icza    7 年前

    我的疑问是: err = json.Unmarshal(body, &p) 为什么我们要将编码体指定给 err

    你没有。你通过了 body json.Unmarshal() 函数,并指定 返回值 犯错误 变量,它告诉您如果解组失败(或如果 犯错误 nil ).

    情况如何 p.Stuff.Fruit 当我看不到分配给的任何内容时获取值 p

    您传递的地址 p json。解组() ,因此它有一个指向变量的指针,如果它修改 指出 值(由指针指向),它修改的值与您拥有的值相同( p ).

    请参见以下简单示例:

    func change(p *int) {
        *p = 3
    }
    
    func main() {
        var i int
        fmt.Println("Before", i)
        change(&i)
        fmt.Println("After", i)
    }
    

    输出(在 Go Playground ):

    Before 0
    After 3
    

    main() 函数我们不给局部变量赋值 i ,但我们将其地址传递给 change() 函数,该函数修改 指出 值,所以如果我们打印 更改() 调用时,我们看到它的值发生了更改。

    您传递的地址 p json。解组() ,因此它将能够修改存储在 p . 在引擎盖下 json 包使用反射(包 reflect )查找的运行时类型 p 并根据传递给它进行解析的JSON文档对其进行修改。

        2
  •  1
  •   Ankit Deshpande    7 年前

    您已经使用创建了指向有效负载的指针 &p 地址运算符。现在它将值保存在p所指的地址。根据Golang规范 Unmarshal 以字节格式和接口{}获取数据,以包装将数据存储在某个地址的变量。

    Unmarshal解析JSON编码的数据,并将结果存储在 v指向的值。如果v为零或不是指针,则解组返回 无效的解组错误。

    Unmarshal函数返回错误

    func Unmarshal(data []byte, v interface{}) error
    
    var m Message
    err := json.Unmarshal(b, &m)
    

    这就是为什么它被分配给一个变量。您可以使用 _ 但这不是一个好方法

    _ := json.Unmarshal(b, &m)