Go 中的通用解组
Generic unmarshalling in Go
我试图弄清楚是否有一种方法可以仅使用字符串和预期类型将 JSON 字符串解组为特定结构。这是我到目前为止的想法。
代码
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Person struct {
Name string `json:"name"`
}
func genericUnmarshal(jsonString string, t reflect.Type) interface{} {
p := reflect.New(t)
result := p.Interface()
json.Unmarshal([]byte(jsonString), &result)
return result
}
func main() {
jsonData := "{\"name\":\"John\"}"
unmarshalledPerson := genericUnmarshal(jsonData, reflect.TypeOf(Person{}))
person := Person{Name: "John"}
fmt.Printf("struct value: %+v type: %+v\n", person, reflect.TypeOf(person))
fmt.Printf("unmarshalled value: %+v type: %+v\n", unmarshalledPerson, reflect.TypeOf(unmarshalledPerson))
fmt.Printf("are variables equal: %v\n", reflect.DeepEqual(unmarshalledPerson, person))
}
Returns
struct value: {Name:John} type: main.Person
unmarshalled value: &{Name:John} type: *main.Person
are variables equal: false
方法genericUnmarshal
returns指向类型的指针。
我的问题:有没有办法将未编组的值更改为结构(即 Person
)而不是指针,以便 reflect.DeepEqual(unmarshalledPerson, person)
returns true
?
您可以比较 person 指针,因为 reflect.DeepEqual()
如果指针值(深度)相等则也接受:
Pointer values are deeply equal if they are equal using Go's == operator or if they point to deeply equal values.
所以简单地做:
fmt.Printf("are variables equal: %v\n",
reflect.DeepEqual(unmarshalledPerson, &person))
或者取消引用包裹在 unmarshalledPerson
中的 *Person
指针,这样你就得到一个 Person
结构:
fmt.Printf("are variables equal: %v\n",
reflect.DeepEqual(*unmarshalledPerson.(*Person), person))
两者都打印 true
(在 Go Playground 上尝试):
are variables equal: true
are variables equal: true
另请注意,对于您的“简单”结构,您可以使用简单的 ==
比较:
*unmarshalledPerson.(*Person) == person
如果您添加其他字段(例如指针、结构、映射等),情况就不会如此
我试图弄清楚是否有一种方法可以仅使用字符串和预期类型将 JSON 字符串解组为特定结构。这是我到目前为止的想法。
代码
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Person struct {
Name string `json:"name"`
}
func genericUnmarshal(jsonString string, t reflect.Type) interface{} {
p := reflect.New(t)
result := p.Interface()
json.Unmarshal([]byte(jsonString), &result)
return result
}
func main() {
jsonData := "{\"name\":\"John\"}"
unmarshalledPerson := genericUnmarshal(jsonData, reflect.TypeOf(Person{}))
person := Person{Name: "John"}
fmt.Printf("struct value: %+v type: %+v\n", person, reflect.TypeOf(person))
fmt.Printf("unmarshalled value: %+v type: %+v\n", unmarshalledPerson, reflect.TypeOf(unmarshalledPerson))
fmt.Printf("are variables equal: %v\n", reflect.DeepEqual(unmarshalledPerson, person))
}
Returns
struct value: {Name:John} type: main.Person
unmarshalled value: &{Name:John} type: *main.Person
are variables equal: false
方法genericUnmarshal
returns指向类型的指针。
我的问题:有没有办法将未编组的值更改为结构(即 Person
)而不是指针,以便 reflect.DeepEqual(unmarshalledPerson, person)
returns true
?
您可以比较 person 指针,因为 reflect.DeepEqual()
如果指针值(深度)相等则也接受:
Pointer values are deeply equal if they are equal using Go's == operator or if they point to deeply equal values.
所以简单地做:
fmt.Printf("are variables equal: %v\n",
reflect.DeepEqual(unmarshalledPerson, &person))
或者取消引用包裹在 unmarshalledPerson
中的 *Person
指针,这样你就得到一个 Person
结构:
fmt.Printf("are variables equal: %v\n",
reflect.DeepEqual(*unmarshalledPerson.(*Person), person))
两者都打印 true
(在 Go Playground 上尝试):
are variables equal: true
are variables equal: true
另请注意,对于您的“简单”结构,您可以使用简单的 ==
比较:
*unmarshalledPerson.(*Person) == person
如果您添加其他字段(例如指针、结构、映射等),情况就不会如此