Files
baseapi/utils/utils_reflect.go
2019-07-14 14:53:29 +08:00

86 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}