- utils_reflect

This commit is contained in:
gazebo
2019-05-24 16:43:21 +08:00
parent 8a5ef089d1
commit 96818a206e
2 changed files with 83 additions and 0 deletions

59
utils/utils_reflect.go Normal file
View File

@@ -0,0 +1,59 @@
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
}

View File

@@ -0,0 +1,24 @@
package utils
import (
"reflect"
"testing"
)
func TestReflect(t *testing.T) {
type SubXXXX struct {
IntData int
StrData string
}
type XXXX struct {
SubXXXX
A int
B string `json:"b"`
}
x := XXXX{}
typeX := reflect.TypeOf(x)
field := typeX.Field(0)
t.Log(IsFieldEmbedded(&field))
t.Log(Format4Output(GetStructObjNameIndex(&x, ""), false))
}