因为我经常解组http.Response.Body
,所以我认为我可以编写一个函数来处理读取,关闭和解组各种不同结构的所有麻烦。这就是为什么我引入了一个函数func unmarhalInterface(closer *io.ReadCloser, v *interface{}) error
,然后可以使用t:=i.(T)
声明返回值的原因。
根据this answer,我已经将其包装为类型为*interface{}
的值,但是由于覆盖类型为interface{}
而不是myStruct
,因此json
包实现选择map[string]interface{}
。之后,类型断言失败(当然)。是我缺少的东西还是需要该实现“手动”类型断言,这意味着在映射中查找所有字段并将所需的字段分配给我的结构。
下面的代码在注释中带有注释的最小示例。如果我的解释还不够,请问。
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
}
答案 0 :(得分:1)
一个空接口不是实际的类型,基本上是可以匹配任何东西的东西。如评论中所述,指向空接口的指针实际上没有任何意义,因为指针已经与空接口匹配,因为所有内容都与空接口匹配。为了使您的代码正常工作,您应该删除结构周围的接口包装,因为这只是搞乱了json类型检查,而空接口的全部目的是您可以将任何内容传递给它。
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 = &myStruct{} // This need to be a pointer so its attributes can be assigned
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:
fmt.Println(foo.A)
}
// You don't need to declare either of these arguments as pointers since they're both interfaces
func unmarshalCloser(closer io.ReadCloser, v interface{}) error {
defer closer.Close()
// v NEEDS to be a pointer or the json stuff will barf
// Simplified with the decoder
return json.NewDecoder(closer).Decode(v)
}