86 lines
2.2 KiB
Go
86 lines
2.2 KiB
Go
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{}) {
|
||
typeInfo := reflect.TypeOf(value)
|
||
if typeInfo.Kind() != reflect.Slice {
|
||
panic("list must be slice type!")
|
||
}
|
||
if value != nil {
|
||
valueInfo := reflect.ValueOf(value)
|
||
retVal = make([]interface{}, valueInfo.Len())
|
||
for i := 0; i < valueInfo.Len(); i++ {
|
||
retVal[i] = valueInfo.Index(i).Interface()
|
||
}
|
||
}
|
||
return retVal
|
||
}
|