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
}
Table of Contents