package utils import ( "reflect" "strings" ) // 得到一个结构体(或指向结构体的指针)中其成员(tag指定,缺省是字段名)的路径(嵌入结构体或指向结构指针会被展开) func GetStructObjNameIndex(obj interface{}, tag string) map[string][]int { objType := reflect.TypeOf(obj) return GetStructNameIndex(objType, tag) } func GetStructNameIndex(objType reflect.Type, tag string) (nameIndex map[string][]int) { if objType.Kind() == reflect.Ptr { objType = objType.Elem() } if objType.Kind() != reflect.Struct { panic("obj must be struct obj or pointer to struct of obj!") } nameIndex = make(map[string][]int) for i := 0; i < objType.NumField(); i++ { structField := objType.Field(i) fieldType := structField.Type if IndirectType(fieldType).Kind() == reflect.Struct && IsFieldEmbedded(&structField) { // 嵌入 subNameIndex := GetStructNameIndex(fieldType, tag) for k, v := range subNameIndex { nameIndex[k] = append([]int{i}, v...) } } else { tagName := structField.Name if tag != "" { tagName2 := strings.Split(structField.Tag.Get(tag), ",")[0] if tagName2 == "-" { tagName = "" // 忽略 } else if tagName2 != "" { tagName = tagName2 } } if tagName != "" { nameIndex[tagName] = []int{i} } } } return nameIndex } // 判断成员是否是嵌入的,依据是成员名与类型名相同 func IsFieldEmbedded(structField *reflect.StructField) bool { return structField.Name == IndirectType(structField.Type).Name() } func IndirectType(objType reflect.Type) reflect.Type { if objType.Kind() == reflect.Ptr { objType = objType.Elem() } return objType } func GetConcretValue(value reflect.Value) reflect.Value { for { if value.Kind() == reflect.Interface || value.Kind() == reflect.Ptr { value = value.Elem() } else { break } } return value } func Interface2Slice(value interface{}) (retVal []interface{}) { if value != nil { typeInfo := reflect.TypeOf(value) if typeInfo.Kind() != reflect.Slice { panic("list must be slice type!") } valueInfo := reflect.ValueOf(value) retVal = make([]interface{}, valueInfo.Len()) for i := 0; i < valueInfo.Len(); i++ { retVal[i] = valueInfo.Index(i).Interface() } } return retVal }