golang reflect
网址
官网: https://golang.org/pkg/reflect/
GO语言中文网: https://studygolang.com/articles/12348?fr=sidebar
代码记录:
pb转Json打印,包含[]byte和指针格式处理:
func StructToMap(ob interface{}, dataMap *map[string]interface{}) {
t := reflect.TypeOf(ob)
v := reflect.ValueOf(ob)
if t.Kind() == reflect.Ptr { // 兼容结构体指针
t = t.Elem()
v = v.Elem()
}
if t.Kind() != reflect.Struct {
fmt.Println("unsupport struct: ", t.Kind())
return
}
//fmt.Printf("ob type: %s, count: %d\n", reflect.TypeOf(ob).String(), t.NumField())
for i := 0; i < t.NumField(); i++ {
key := t.Field(i)
val := v.Field(i)
switch key.Type.Kind() {
case reflect.Ptr: // 处理指针, 如: *string ptr OR *com_tencent_mobileqq_mp.VideoInfo
rVal := val.Elem()
if rVal.Kind() == reflect.Invalid { // 零值处理
switch key.Type.String() {
case "*string":
(*dataMap)[key.Name] = ""
case "*uint32", "*float64", "*int":
(*dataMap)[key.Name] = 0
}
} else {
if rVal.Kind() == reflect.Struct { // 结构体处理,递归
if v.Field(i).IsValid() {
newMap := make(map[string]interface{})
StructToMap(rVal.Interface(), &newMap)
(*dataMap)[key.Name] = newMap
}
} else { // 普通值处理
(*dataMap)[key.Name] = rVal.Interface()
}
}
case reflect.Slice: // 处理切片
if val.IsValid() {
if val.Len() > 0 {
//fmt.Printf("key name: %s, val: %s, key type: %s\n", key.Name, val, key.Type.String())
switch key.Type.String() {
case "[]uint8": // []byte
(*dataMap)[key.Name] = string(val.Bytes())
default: // []Struct []*Struct
fmt.Printf("key name: %s, val len: %d, val cap: %d\n", key.Name, val.Len(), val.Cap())
var dataList []interface{}
dataSlice := val.Slice(0, val.Len())
for i := 0; i < val.Len(); i++ {
if dataSlice.Index(i).Kind() == reflect.Ptr {
dataList = append(dataList, dataSlice.Index(i).Elem().Interface())
} else {
dataList = append(dataList, dataSlice.Index(i).Interface())
}
}
(*dataMap)[key.Name] = dataList
}
} else { // 零值处理
//fmt.Printf("len zero flow, key name: %s, val: %s, key type: %s\n", key.Name, val, key.Type.String())
switch key.Type.String() {
case "[]uint8": // []byt
(*dataMap)[key.Name] = "" // []byte零值是nil
default: // []Struct []*Struct
(*dataMap)[key.Name] = nil // 其他slice零值是nil
}
}
} else { // 零值处理
//fmt.Printf("zero val flow, key name: %s, val: %s, key type: %s\n", key.Name, val, key.Type.String())
(*dataMap)[key.Name] = nil
}
case reflect.Struct:
if v.Field(i).IsValid() {
newMap := make(map[string]interface{})
StructToMap(v.Field(i).Interface(), &newMap)
(*dataMap)[key.Name] = newMap
}
}
}
//fmt.Println("data map: ", *dataMap)
return
}