- 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