github.com/searKing/golang/go@v1.2.117/encoding/internal/tag/field.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tag 6 7 import ( 8 "reflect" 9 "sync" 10 11 reflect_ "github.com/searKing/golang/go/reflect" 12 ) 13 14 // A field represents a single field found in a struct. 15 type field struct { 16 name string 17 structTag reflect.StructTag 18 19 index []int 20 typ reflect.Type 21 } 22 23 var fieldCache fieldMap 24 25 type fieldMap struct { 26 fields sync.Map // map[reflect.Type][]field 27 } 28 29 func (m *fieldMap) Store(type_ reflect.Type, fields []field) { 30 m.fields.Store(type_, fields) 31 } 32 33 func (m *fieldMap) LoadOrStore(type_ reflect.Type, fields []field) ([]field, bool) { 34 actual, loaded := m.fields.LoadOrStore(type_, fields) 35 if actual == nil { 36 return nil, loaded 37 } 38 return actual.([]field), loaded 39 } 40 41 func (m *fieldMap) Load(type_ reflect.Type) ([]field, bool) { 42 fields, ok := m.fields.Load(type_) 43 if fields == nil { 44 return nil, ok 45 } 46 return fields.([]field), ok 47 } 48 49 func (m *fieldMap) Delete(type_ reflect.Type) { 50 m.fields.Delete(type_) 51 } 52 53 func (m *fieldMap) Range(f func(type_ reflect.Type, fields []field) bool) { 54 m.fields.Range(func(type_, fields any) bool { 55 return f(type_.(reflect.Type), fields.([]field)) 56 }) 57 } 58 59 // cachedTypeFields is like typeFields but uses a cache to avoid repeated work. 60 func cachedTypeFields(t reflect.Type) []field { 61 if f, ok := fieldCache.Load(t); ok { 62 return f 63 } 64 var fields []field 65 reflect_.WalkTypeDFS(t, reflect_.FieldTypeInfoHandlerFunc( 66 func(info reflect_.FieldTypeInfo) (goon bool) { 67 // ignore struct's root 68 if info.Depth() == 0 { 69 return true 70 } 71 72 sf, ok := info.StructField() 73 if !ok { 74 return true 75 } 76 77 fields = append(fields, field{ 78 name: sf.Name, 79 structTag: sf.Tag, 80 index: info.Index(), 81 typ: sf.Type, 82 }) 83 return true 84 })) 85 f, _ := fieldCache.LoadOrStore(t, fields) 86 return f 87 }