github.com/zhongdalu/gf@v1.0.0/g/internal/structs/structs_tag.go (about) 1 // Copyright 2019 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 package structs 8 9 import ( 10 "reflect" 11 12 "github.com/zhongdalu/gf/third/github.com/fatih/structs" 13 ) 14 15 // TagMapName retrieves struct tags as map[tag]attribute from <pointer>, and returns it. 16 // 17 // The parameter <recursive> specifies whether retrieving the struct field recursively. 18 // 19 // Note that it only retrieves the exported attributes with first letter up-case from struct. 20 func TagMapName(pointer interface{}, priority []string, recursive bool) map[string]string { 21 tagMap := TagMapField(pointer, priority, recursive) 22 if len(tagMap) > 0 { 23 m := make(map[string]string, len(tagMap)) 24 for k, v := range tagMap { 25 m[k] = v.Name() 26 } 27 return m 28 } 29 return nil 30 } 31 32 // TagMapField retrieves struct tags as map[tag]*Field from <pointer>, and returns it. 33 // 34 // The parameter <recursive> specifies whether retrieving the struct field recursively. 35 // 36 // Note that it only retrieves the exported attributes with first letter up-case from struct. 37 func TagMapField(pointer interface{}, priority []string, recursive bool) map[string]*Field { 38 tagMap := make(map[string]*Field) 39 fields := ([]*structs.Field)(nil) 40 if v, ok := pointer.(reflect.Value); ok { 41 fields = structs.Fields(v.Interface()) 42 } else { 43 rv := reflect.ValueOf(pointer) 44 kind := rv.Kind() 45 if kind == reflect.Ptr { 46 rv = rv.Elem() 47 kind = rv.Kind() 48 } 49 // If pointer is type of **struct and nil, then automatically create a temporary struct, 50 // which is used for structs.Fields. 51 if kind == reflect.Ptr && (!rv.IsValid() || rv.IsNil()) { 52 fields = structs.Fields(reflect.New(rv.Type().Elem()).Elem().Interface()) 53 } else { 54 fields = structs.Fields(pointer) 55 } 56 } 57 tag := "" 58 name := "" 59 for _, field := range fields { 60 name = field.Name() 61 // Only retrieve exported attributes. 62 if name[0] < byte('A') || name[0] > byte('Z') { 63 continue 64 } 65 66 tag = "" 67 for _, p := range priority { 68 tag = field.Tag(p) 69 if tag != "" { 70 break 71 } 72 } 73 if tag != "" { 74 tagMap[tag] = field 75 } 76 if recursive { 77 rv := reflect.ValueOf(field.Value()) 78 kind := rv.Kind() 79 if kind == reflect.Ptr { 80 rv = rv.Elem() 81 kind = rv.Kind() 82 } 83 if kind == reflect.Struct { 84 for k, v := range TagMapField(rv, priority, true) { 85 if _, ok := tagMap[k]; !ok { 86 tagMap[k] = v 87 } 88 } 89 } 90 } 91 } 92 return tagMap 93 }