猿问

通过引用分配

我在 Go 中遇到了一个小任务的参考问题。我试图在下面的代码中模仿这个问题。


package main


import (

    "encoding/json"

    "fmt"

)


type tRes struct {

    a string

    b interface{}

}


func get(t string, r interface{}) error {

    var res tRes

    switch t {

    case "string":

        res = tRes{

            a: "XYZ",

            b: "Nobody",

        }

    case "int":

        res = tRes{

            a: "XYZ",

            b: 10,

        }

    }

    // r = &res.b

    j, _ := json.Marshal(res.b)

    json.Unmarshal(j, &r)

    return nil

}


func main() {

    var b string

    get("string", &b)

    fmt.Println(b)

    

    var i int

    get("int", &i)

    fmt.Println(i)

}

在代码中,get 方法根据类型返回一个值。如果我使用r = &res.b它不起作用而j, _ := json.Marshal(res.b) json.Unmarshal(j, &r)起作用。我不想像在实际代码中那样对一个非常大的对象执行 json marshal 和 unmarshal,我正在调用一个返回大对象的 API。我执行 json unmarshal 来创建主对象,然后将一个子对象(定义为 interface{})分配给响应(可能是不同的类型)作为对我不起作用的参考。


四季花海
浏览 84回答 2
2回答

摇曳的蔷薇

目标是b在解组之前设置字段的类型。使用以下代码:func get(data []byte, r interface{}) error {    res := struct {        A string        B interface{}    }{        B: r,    }    return json.Unmarshal(data, &res)}像这样称呼它:func main() {    var b string    get([]byte(`{"a": "XYZ", "b": "Nobody"}`), &b)    fmt.Println(b)    var i int    get([]byte(`{"a": "XYZ", "b": 10}`), &i)    fmt.Println(i)}

慕的地6264312

您正在将interface{}值传递给您的get函数。由于它是按值传递的,因此您的r = &res.b赋值将覆盖函数中的值,这对引用中包含的值没有影响。换句话说:r 一个interface{}指的是一个指针指向 astring或 a int。您的代码修改本地值r以引用指向 astring或a 的新指针int,忽略并丢弃传入的原始指针。如果要修改指针的目标,则需要访问它。在您的接口类型上使用类型转换(例如if rstringptr, ok := r.(*string); ok { ... }或类型开关)以获取其中引用的适当类型的值。这甚至可以让您简化 API,因为您不需要在单独的参数中提供类型。例如:import "fmt"func get(iface interface{}) {  switch concrete := iface.(type) {  case *string:    *concrete = "Nobody"  case *int:    *concrete = 10  }}func main() {    var b string    get(&b)    fmt.Println(b)        var i int    get(&i)    fmt.Println(i)}https://play.golang.org/p/JyYRjH9DchjNobody10
随时随地看视频慕课网APP

相关分类

Go
我要回答