gpt4 book ai didi

go - 为什么 unmarshal 使 golang 中的对象类型发生变化

转载 作者:数据小太阳 更新时间:2023-10-29 03:44:17 27 4
gpt4 key购买 nike

我想编写一个 mockData 方法,它可以接受多种类型的参数并根据其 json 数据返回相应的对象。代码如下:

func MockData(jsonPath string,v interface{})(interface{},error){
var ret interface{}
data,_ := ioutil.ReadFile(jsonPath)
switch v.(type) {
case Req:
ret = Req{}
fmt.Printf("\n===before Unmarshal==%T===\n",ret)
err = json.Unmarshal(data,&ret)
if err!=nil{...}
fmt.Printf("======after unmarshal===%T\n",ret)
case ...
default:
fmt.Printf("error===not match")
}
return ret,err
}

但是,当我使用它时,它会出现 panic 。代码如下:

func main(){
reqJsonPath := /xx/yy/req.json
obj,err:=test.MockData(jsonFile,Req{})
if err!=nil{...}
require := obj.(Req) //panic cant []interface{} to Req
}

MockData 的输出是:

===before Unmarshal==Req===
======after unmarshal===[]interface{}

对象的类型在解码后发生了变化。更奇怪的是,如果我替换:

ret = Req{}

ret = &Req{}

输出将与以下相同:

===before Unmarshal==*Req===
======after unmarshal===*Req

为了更方便地重现问题,我给出了如下的 Require 结构:

type Req []*Ele
type Ele struct {
ID int
Level int
}

总结:

  1. 我能否实现根据其 json 和类型生成不同类型对象的预期功能?
  2. 为什么解码后对象的类型发生了变化,而添加 & 后却没有发生变化?

最佳答案

Can I achieve expected function which produces different types of objects based on its json and type?

func MockData(filename string, v interface{}) (interface{}, error) {

data, _ := ioutil.ReadFile(filename)
switch t := v.(type) {
case Req:
// t at this point is a Req{}
err := json.Unmarshal(data, &t)
return t, err
}
return nil, errors.New("unknown type")
}

我真的不知道您为什么需要传递实际结构而不是指针的动机。 Check this demonstration

Why does the type of object changed after unmarshal, and why it not changed after I add &?

当您使用 &ret 解码时,其中 ret 是一个接口(interface),您将获得该接口(interface)的地址。因此,json.Unmarshal() 将看到支持数据是一个接口(interface)而不是指向结构的指针。 json.Unmarshal() 将使用的默认数据类型是对象的 map[string]interface{} 和对象的 []interface{}数组。

现在,如果您使用 ret 解码,其中 ret&Req{}json.Unmarshal() 将检查支持数据是否为 ​​struct,因此它可以使用结构的字段进行解码。

编辑:

您似乎对指向接口(interface)的指针感到困惑,它不同于具有指针的接口(interface)。试试这段代码,您会发现不同之处。

var x interface{} = Req{}
var y interface{} = &x
var z interface{} = &Req{}

fmt.Printf("%T\n", y)
fmt.Printf("%T\n", z)

请记住,接口(interface)只是普通值,它们也会占用内存。现在,如果您获取该内存的地址,您将获得指向接口(interface)的指针,而不是指向接口(interface)所引用数据的指针。

关于go - 为什么 unmarshal 使 golang 中的对象类型发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53440269/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com