【问题标题】:How does json.Unmarshal() work and how is it stored in a variable?json.Unmarshal() 如何工作以及它如何存储在变量中?
【发布时间】:2018-08-05 17:45:06
【问题描述】:

刚开始使用 Go,我对正在学习的教程有一点疑问。我读到Unmarshall 是某种 JSON 编码,我的疑问是:err = json.Unmarshal(body, &p) 为什么我们将编码主体分配给 err 以及当我看不到分配给的任何内容时,p.Stuff.Fruit 如何获得值p.

注意:produce 是不同的包,其中包含一些类型和数组。*

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)
}

【问题讨论】:

  • 经验法则:阅读软件包文档。总是,即使遵循一些随机教程。

标签: json pointers go unmarshalling


【解决方案1】:

我的疑问是:err = json.Unmarshal(body, &p) 为什么我们将编码的正文分配给err

你没有。您将body 传递给json.Unmarshal() 函数,并将其返回值 分配给err 变量,该变量告诉您​​解组是否失败(或者如果errnil 则成功)。

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

你将p的地址传递给json.Unmarshal(),所以它有一个指向你的变量的指针,所以如果它修改pointed值(由指针指向),它会修改您拥有相同的值 (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() 函数,该函数修改了 pointed 值,因此如果我们在调用change() 之后打印i 的值,我们会看到它的值发生了变化。

您将p 的地址传递给json.Unmarshal(),因此它将能够修改存储在p 中的值。在底层,json 包使用反射(包reflect)来发现p 的运行时类型,并根据您传递给它解析的 JSON 文档对其进行修改。

【讨论】:

    【解决方案2】:

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

    Unmarshal 解析 JSON 编码的数据并将结果存储在 v 指向的值。如果 v 为 nil 或不是指针,Unmarshal 返回 一个 InvalidUnmarshalError。

    Unmarshal 函数返回错误

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 2023-03-14
      • 2012-05-26
      • 2011-05-04
      • 1970-01-01
      相关资源
      最近更新 更多