- utils_reflect
This commit is contained in:
59
utils/utils_reflect.go
Normal file
59
utils/utils_reflect.go
Normal 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
|
||||
}
|
||||
24
utils/utils_reflect_test.go
Normal file
24
utils/utils_reflect_test.go
Normal 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))
|
||||
}
|
||||
Reference in New Issue
Block a user