【发布时间】:2019-06-19 17:37:40
【问题描述】:
因为我经常解组http.Response.Body,所以我想我可以编写一个函数来处理读取、关闭和解组到各种不同结构的所有麻烦。这就是为什么我引入了一个函数func unmarhalInterface(closer *io.ReadCloser, v *interface{}) error,然后可以使用t:=i.(T) 断言返回值。
根据this answer,我已经将它包装成一个*interface{}类型的值,但是因为上面的类型是interface{}而不是myStruct,所以json包实现选择map[string]interface{}。之后类型断言失败(当然)。有什么我遗漏的或者需要这个实现“手动”的类型断言,这意味着查找地图中的所有字段并将我想要的那些分配到我的结构中。
下面的代码有一个用 cmets 表示的最小示例。如果我的解释不充分,请尽管问。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
)
type myStruct struct {
A string `json:"a"`
B string `json:"b"`
}
func main() {
jsonBlob := []byte(`{"a":"test","b":"test2"}`)
var foo = interface{}(myStruct{})
closer := ioutil.NopCloser(bytes.NewReader(jsonBlob))
err := unmarshalCloser(&closer, &foo)
if err != nil {
log.Fatal(err)
}
fmt.Println(fmt.Sprintf("%v", foo))
// That´s what i want:
foo2 := foo.(myStruct)
fmt.Println(foo2.A)
}
func unmarshalCloser(closer *io.ReadCloser, v *interface{}) error {
defer func() { _ = (*closer).Close() }()
data, err := ioutil.ReadAll(*closer)
if err != nil {
return err
}
err = json.Unmarshal(data, v)
if err != nil {
return err
}
return nil
}
【问题讨论】:
-
链接的答案说不使用
*interface{}。唯一需要指向接口的指针是如果您想将一个空接口传递给Unmarshal本身。另外,为什么你还有*io.ReadCloser作为参数?几乎没有理由传递指向接口的指针(如果您想通过反射分配给接口,上述例外是少数例外之一) -
@j 我也试过没有指针,但同样的问题仍然存在。相同的接口转换问题,即使 json.unmarshal 现在获取正确的类型作为输入。 NotPointerCode:play.golang.org/p/edn5opF50SQ
-
试过什么?如果您删除所有接口指针废话,它会按预期工作:play.golang.org/p/GfJFvhVad3w。这与您想要实现的目标有何不同?
标签: json go unmarshalling