【发布时间】:2018-11-23 03:19:15
【问题描述】:
我想写一个 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
}
但是,当我使用它时,它会出现恐慌。代码如下:
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
}
总结:
- 能否实现预期的功能,根据其 json 和类型生成不同类型的对象?
- 为什么解组后对象的类型改变了,为什么我添加 & 后它没有改变?
【问题讨论】:
-
变量
ret是interface{}类型,该类型用于解组。反射很复杂,而且您的 Printfs 不能像您期望的那样工作。阅读博客文章反射定律。您实际上必须解组为 common.Require(而不是空接口),因此将变量 decl 移动到类型开关中。 -
common.Require定义在哪里? -
@Flimzy 哦,为了简化问题,我将 common.Require 替换为 Req,我会更新它。
标签: go interface unmarshalling