Luf*_*liu 7 reflection struct go recursive-datastructures
我有一个嵌套的三层结构。我想在Go中使用reflect来解析它(使用递归函数)。使用反射和递归函数的原因是
这是一些代码。
type Edge struct{
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Read Article `json:"visited,omitempty"`
}
type Article struct {
Uid string`json:"uid,omitempty"`
Namestring`json:"name,omitempty"`
From Site `json:"from,omitempty"`
}
type Site struct{
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
}
func CheckNestedStruct(edges interface{}){
rv := reflect.ValueOf(edges).Elem()
uidField := rv.FieldByName("Uid")
uid := getStructField(edges, "Name") // get value of Name from database
if (uid != ""){
uidField.SetString(uid)
}
for i := 0 ; i < rv.NumField() ; i++ {
field := rv.Field(i)
fieldType := field.Kind()
if (fieldType == reflect.Struct){
CheckNestedStruct(field)
}
}
}
func main(){
....
var edges Edges{
...
...
}
CheckNestedStruct(&edges)
}
Run Code Online (Sandbox Code Playgroud)
当我运行这个时,在第一层我得到“ type: *entity.SacWebIS ”。然而,在第二次迭代/递归中,我得到了“ type: *reflect.rtype ”。我也尝试过field.Interface()。如何修改这段代码呢?谢谢。
更新
解决办法是
CheckNestedStruct(dg, field.Addr().Interface())
Run Code Online (Sandbox Code Playgroud)
您正在调用reflect.ValueOfa reflect.Value,这就是为您提供类型的原因*reflect.rtype。如果你想将reflect.Value返回值传递给同一个函数,你需要先调用Interface().
CheckNestedStruct(field.Interface())
Run Code Online (Sandbox Code Playgroud)
然后,Elem无论您是对指针还是值进行操作,都可以进行调用。如果您想有条件地间接一个值,请使用reflect.Indirect
rv := reflect.Indirect(reflect.ValueOf(edges))
Run Code Online (Sandbox Code Playgroud)
为了在不知道字段的值和类型的情况下解析未知的 json,您需要创建一个递归函数,该函数将解析深度嵌套的底层值。您可以使用类型断言获得最终值。
func main() {
m, ok := myJson.(map[string]interface{})
newM := iterate(m)
jsonBytes, err := json.Marshal(newM)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(jsonBytes))
}
Run Code Online (Sandbox Code Playgroud)
对于将 json 解组到接口的记录,它主要将嵌套结构转换为两种类型:接口切片[]interface{}或接口映射,map[string]interface{}直到我们获得可以使用的嵌套结构的最终值Interface()。因此,我们可以为深度嵌套创建递归结构。
func iterate(data interface{}) interface{} {
if reflect.ValueOf(data).Kind() == reflect.Slice {
d := reflect.ValueOf(data)
tmpData := make([]interface{}, d.Len())
returnSlice := make([]interface{}, d.Len())
for i := 0; i < d.Len(); i++ {
tmpData[i] = d.Index(i).Interface()
}
for i, v := range tmpData {
returnSlice[i] = iterate(v)
}
return returnSlice
} else if reflect.ValueOf(data).Kind() == reflect.Map {
d := reflect.ValueOf(data)
tmpData := make(map[string]interface{})
for _, k := range d.MapKeys() {
typeOfValue := reflect.TypeOf(d.MapIndex(k).Interface()).Kind()
if typeOfValue == reflect.Map || typeOfValue == reflect.Slice {
tmpData[k.String()] = iterate(d.MapIndex(k).Interface())
} else {
tmpData[k.String()] = d.MapIndex(k).Interface()
}
}
return tmpData
}
return data
}
Run Code Online (Sandbox Code Playgroud)
最后,interface{} 的底层值将是原始类型string, float64, bool。
func identify(output map[string]interface{}) {
fmt.Printf("%T", output)
for a, b := range output {
switch bb := b.(type) {
case string:
fmt.Println("This is a string")
case float64:
fmt.Println("this is a float")
case bool:
fmt.Println("this is a boolean")
case []interface{}:
// Access the values in the JSON object and place them in an Item
for _, itemValue := range jsonObj {
fmt.Printf("%v is an interface\n", itemValue)
identify(itemValue.(map[string]interface{}))
}
default:
return
}
}
}
Run Code Online (Sandbox Code Playgroud)