github.com/kaydxh/golang@v0.0.131/go/reflect/struct.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package reflect 23 24 import ( 25 "reflect" 26 ) 27 28 //req must be pointer to struct 29 // IsNil reports whether its argument v is nil. The argument must be 30 // a chan, func, interface, map, pointer, or slice value; if it is 31 // not, IsNil panics. Note that IsNil is not always equivalent to a 32 // regular comparison with nil in Go. For example, if v was created 33 // by calling ValueOf with an uninitialized interface variable i, 34 // i==nil will be true but v.IsNil will panic as v will be the zero 35 // Value. 36 func indirectStruct(req interface{}) (reflect.Value, bool) { 37 if req == nil { 38 return reflect.Value{}, false 39 } 40 41 v := reflect.ValueOf(req) 42 /* 43 if v.IsNil() { 44 return reflect.Value{}, false 45 } 46 */ 47 48 return reflect.Indirect(v), true 49 } 50 51 func RetrieveStructField(req interface{}, name string) string { 52 v, ok := indirectStruct(req) 53 if !ok { 54 return "" 55 } 56 57 if !v.IsValid() { 58 return "" 59 } 60 61 //nested field: reflect.Indirect(v).FieldByName("layout1").Index(0).FieldByName("layout2") 62 f := v.FieldByName(name) 63 if f.IsValid() && f.Kind() == reflect.String { 64 return f.String() 65 } 66 return "" 67 68 } 69 70 func TrySetStructFiled(req interface{}, name, value string) { 71 v, ok := indirectStruct(req) 72 if !ok { 73 return 74 } 75 76 if !v.IsValid() { 77 return 78 } 79 80 f := v.FieldByName(name) 81 if f.IsValid() && f.Kind() == reflect.String { 82 f.SetString(value) 83 } 84 } 85 86 func AllFieldTags(req interface{}, key string) []string { 87 return fieldTags(req, key, false) 88 } 89 90 // req must be struct(Not pointer to struct), or return nil(tt.Field() will panic) 91 // key for tag , db or json, if key is empty, use field name instead 92 func NonzeroFieldTags(req interface{}, key string) []string { 93 return fieldTags(req, key, true) 94 } 95 96 // req must be struct(Not pointer to struct), or return nil(tt.Field() will panic) 97 // key for tag , db or json, if key is empty, use field name instead 98 //nonzere true, noly return field tags for values that nonzero 99 func fieldTags(req interface{}, key string, nonzero bool) []string { 100 var tags []string 101 102 tagsValues := fieldTagsValues(req, key, nonzero) 103 for tag := range tagsValues { 104 tags = append(tags, tag) 105 } 106 107 return tags 108 } 109 110 // only get export Fields 111 func AllTagsValues(req interface{}, key string) map[string]interface{} { 112 return fieldTagsValues(req, key, false) 113 } 114 115 // req must be struct(Not pointer to struct), or return nil(tt.Field() will panic) 116 // key for tag , db or json ..., if key is empty or tag is empty, ignore it 117 // nonzere true, noly return field tags for values that nonzero 118 func fieldTagsValues(req interface{}, key string, nonzero bool) map[string]interface{} { 119 if req == nil { 120 return nil 121 } 122 123 v, ok := indirectStruct(req) 124 if !ok { 125 return nil 126 } 127 if !v.IsValid() { 128 return nil 129 } 130 131 tt := reflect.TypeOf(req) 132 if tt.Kind() == reflect.Ptr { 133 tt = tt.Elem() 134 } 135 136 if tt.Kind() != reflect.Struct { 137 return nil 138 } 139 140 tagsValues := make(map[string]interface{}) 141 for i := 0; i < tt.NumField(); i++ { 142 field := tt.Field(i) 143 property := string(field.Name) 144 f := v.FieldByName(property) 145 146 if !f.CanInterface() { 147 continue 148 } 149 150 if nonzero { 151 if IsZeroValue(f) { 152 continue 153 } 154 } 155 156 if key == "" { 157 continue 158 } 159 160 tag := field.Tag.Get(key) 161 if len(tag) > 0 { 162 // field.Type.Name() -> "string", "int64" ... 163 tagsValues[tag] = f.Interface() 164 } 165 } 166 167 return tagsValues 168 }