@@ -724,100 +724,6 @@ func (t *rawType) rawField(n int) rawStructField {
724
724
return rawStructFieldFromPointer (descriptor , field .fieldType , data , flagsByte , name , offset )
725
725
}
726
726
727
- // rawFieldByNameFunc returns nearly the same value as FieldByNameFunc but without converting the
728
- // Type member to an interface.
729
- //
730
- // For internal use only.
731
- func (t * rawType ) rawFieldByNameFunc (match func (string ) bool ) (rawStructField , []int , bool ) {
732
- if t .Kind () != Struct {
733
- panic (errTypeField )
734
- }
735
-
736
- type fieldWalker struct {
737
- t * rawType
738
- index []int
739
- }
740
-
741
- queue := make ([]fieldWalker , 0 , 4 )
742
- queue = append (queue , fieldWalker {t , nil })
743
-
744
- for len (queue ) > 0 {
745
- type result struct {
746
- r rawStructField
747
- index []int
748
- }
749
-
750
- var found []result
751
- var nextlevel []fieldWalker
752
-
753
- // For all the structs at this level..
754
- for _ , ll := range queue {
755
- // Iterate over all the fields looking for the matching name
756
- // Also calculate field offset.
757
-
758
- descriptor := (* structType )(unsafe .Pointer (ll .t .underlying ()))
759
- field := & descriptor .fields [0 ]
760
-
761
- for i := uint16 (0 ); i < descriptor .numField ; i ++ {
762
- data := field .data
763
-
764
- // Read some flags of this field, like whether the field is an embedded
765
- // field. See structFieldFlagAnonymous and similar flags.
766
- flagsByte := * (* byte )(data )
767
- data = unsafe .Add (data , 1 )
768
-
769
- offset , lenOffs := uvarint32 (unsafe .Slice ((* byte )(data ), maxVarintLen32 ))
770
- data = unsafe .Add (data , lenOffs )
771
-
772
- name := readStringZ (data )
773
- data = unsafe .Add (data , len (name ))
774
- if match (name ) {
775
- found = append (found , result {
776
- rawStructFieldFromPointer (descriptor , field .fieldType , data , flagsByte , name , offset ),
777
- append (ll .index , int (i )),
778
- })
779
- }
780
-
781
- structOrPtrToStruct := field .fieldType .Kind () == Struct || (field .fieldType .Kind () == Pointer && field .fieldType .elem ().Kind () == Struct )
782
- if flagsByte & structFieldFlagIsEmbedded == structFieldFlagIsEmbedded && structOrPtrToStruct {
783
- embedded := field .fieldType
784
- if embedded .Kind () == Pointer {
785
- embedded = embedded .elem ()
786
- }
787
-
788
- nextlevel = append (nextlevel , fieldWalker {
789
- t : embedded ,
790
- index : append (ll .index , int (i )),
791
- })
792
- }
793
-
794
- // update offset/field pointer if there *is* a next field
795
- if i < descriptor .numField - 1 {
796
- // Increment pointer to the next field.
797
- field = (* structField )(unsafe .Add (unsafe .Pointer (field ), unsafe .Sizeof (structField {})))
798
- }
799
- }
800
- }
801
-
802
- // found multiple hits at this level
803
- if len (found ) > 1 {
804
- return rawStructField {}, nil , false
805
- }
806
-
807
- // found the field we were looking for
808
- if len (found ) == 1 {
809
- r := found [0 ]
810
- return r .r , r .index , true
811
- }
812
-
813
- // else len(found) == 0, move on to the next level
814
- queue = append (queue [:0 ], nextlevel ... )
815
- }
816
-
817
- // didn't find it
818
- return rawStructField {}, nil , false
819
- }
820
-
821
727
// Bits returns the number of bits that this type uses. It is only valid for
822
728
// arithmetic types (integers, floats, and complex numbers). For other types, it
823
729
// will panic.
@@ -1096,46 +1002,36 @@ func (t *rawType) PkgPath() string {
1096
1002
return ""
1097
1003
}
1098
1004
1005
+ //go:inline
1099
1006
func (t * rawType ) FieldByName (name string ) (StructField , bool ) {
1100
- if t .Kind () != Struct {
1101
- panic (errTypeFieldByName )
1102
- }
1103
-
1104
- field , index , ok := t .rawFieldByNameFunc (func (n string ) bool { return n == name })
1105
- if ! ok {
1106
- return StructField {}, false
1107
- }
1108
-
1109
- return StructField {
1110
- Name : field .Name ,
1111
- PkgPath : field .PkgPath ,
1112
- Type : field .Type , // note: converts rawType to Type
1113
- Tag : field .Tag ,
1114
- Anonymous : field .Anonymous ,
1115
- Offset : field .Offset ,
1116
- Index : index ,
1117
- }, true
1007
+ return t .FieldByNameFunc (func (n string ) bool { return n == name })
1118
1008
}
1119
1009
1120
1010
func (t * rawType ) FieldByNameFunc (match func (string ) bool ) (StructField , bool ) {
1121
1011
if t .Kind () != Struct {
1122
1012
panic (TypeError {"FieldByNameFunc" })
1123
1013
}
1124
1014
1125
- field , index , ok := t .rawFieldByNameFunc (match )
1126
- if ! ok {
1127
- return StructField {}, false
1015
+ var matchedField * StructField
1016
+ for _ , field := range VisibleFields (Type (t )) {
1017
+ if ! match (field .Name ) {
1018
+ continue
1019
+ }
1020
+
1021
+ if matchedField == nil || len (field .Index ) < len (matchedField .Index ) {
1022
+ // First hit, or hit is in a shallower level
1023
+ matchedField = & field
1024
+ } else if len (field .Index ) == len (matchedField .Index ) {
1025
+ // Multiple hits at this level
1026
+ break
1027
+ }
1128
1028
}
1129
1029
1130
- return StructField {
1131
- Name : field .Name ,
1132
- PkgPath : field .PkgPath ,
1133
- Type : field .Type , // note: converts rawType to Type
1134
- Tag : field .Tag ,
1135
- Anonymous : field .Anonymous ,
1136
- Offset : field .Offset ,
1137
- Index : index ,
1138
- }, true
1030
+ if matchedField != nil {
1031
+ return * matchedField , true
1032
+ }
1033
+
1034
+ return StructField {}, false
1139
1035
}
1140
1036
1141
1037
func (t * rawType ) FieldByIndex (index []int ) StructField {
0 commit comments