--- /dev/null
+pkg reflect, type Type interface, Fields() iter.Seq[StructField] #66631
+pkg reflect, type Type interface, Methods() iter.Seq[Method] #66631
+pkg reflect, type Type interface, Ins() iter.Seq[Type] #66631
+pkg reflect, type Type interface, Outs() iter.Seq[Type] #66631
+pkg reflect, method (Value) Fields() iter.Seq2[StructField, Value] #66631
+pkg reflect, method (Value) Methods() iter.Seq2[Method, Value] #66631
--- /dev/null
+[reflect.Type] includes new methods that return iterators for a type's fields, methods, inputs and outputs.
+Similarly, [reflect.Value] includes two new methods that return iterators over a value's fields or methods,
+each element being a pair of the value ([reflect.Value]) and its type information ([reflect.StructField] or
+[reflect.Method]).
t.Fatalf("test case has different number of inputs and outputs: %d in, %d out", typ.NumIn(), typ.NumOut())
}
var args []reflect.Value
- for i := 0; i < typ.NumIn(); i++ {
- args = append(args, genValue(t, typ.In(i), r))
+ for arg := range typ.Ins() {
+ args = append(args, genValue(t, arg, r))
}
results := fn.Call(args)
for i := range results {
go func() {
defer wg.Done()
ipT := TypeOf(net.IP{})
- for i := 0; i < ipT.NumMethod(); i++ {
- _ = ipT.Method(i)
+ for range ipT.Methods() {
}
}()
}
s.ArrayInt_1024_NoZero[512] = 1
source := ValueOf(s)
- for i := 0; i < source.NumField(); i++ {
- name := source.Type().Field(i).Name
- value := source.Field(i)
- b.Run(name, func(b *testing.B) {
+ for field, value := range source.Fields() {
+ b.Run(field.Name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
sink = value.IsZero()
}
Struct Value
})).Elem()
- for i := 0; i < source.NumField(); i++ {
- name := source.Type().Field(i).Name
- value := source.Field(i)
+ for field, value := range source.Fields() {
+ name := field.Name
zero := Zero(value.Type())
b.Run(name+"/Direct", func(b *testing.B) {
for i := 0; i < b.N; i++ {
s := S{}
st := reflect.TypeOf(s)
- for i := 0; i < st.NumField(); i++ {
- field := st.Field(i)
+ for field := range st.Fields() {
if alias, ok := field.Tag.Lookup("alias"); ok {
if alias == "" {
fmt.Println("(blank)")
import (
"internal/abi"
"internal/goarch"
+ "iter"
"runtime"
"strconv"
"sync"
// This may make the executable binary larger but will not affect execution time.
Method(int) Method
+ // Methods returns an iterator over each method in the type's method set. The sequence is
+ // equivalent to calling Method successively for each index i in the range [0, NumMethod()).
+ Methods() iter.Seq[Method]
+
// MethodByName returns the method with that name in the type's
// method set and a boolean indicating if the method was found.
//
// It panics if i is not in the range [0, NumField()).
Field(i int) StructField
+ // Fields returns an iterator over each struct field for struct type t. The sequence is
+ // equivalent to calling Field successively for each index i in the range [0, NumField()).
+ // It panics if the type's Kind is not Struct.
+ Fields() iter.Seq[StructField]
+
// FieldByIndex returns the nested field corresponding
// to the index sequence. It is equivalent to calling Field
// successively for each index i.
// It panics if i is not in the range [0, NumIn()).
In(i int) Type
+ // Ins returns an iterator over each input parameter of function type t. The sequence
+ // is equivalent to calling In successively for each index i in the range [0, NumIn()).
+ // It panics if the type's Kind is not Func.
+ Ins() iter.Seq[Type]
+
// Key returns a map type's key type.
// It panics if the type's Kind is not Map.
Key() Type
// It panics if i is not in the range [0, NumOut()).
Out(i int) Type
+ // Outs returns an iterator over each output parameter of function type t. The sequence
+ // is equivalent to calling Out successively for each index i in the range [0, NumOut()).
+ // It panics if the type's Kind is not Func.
+ Outs() iter.Seq[Type]
+
// OverflowComplex reports whether the complex128 x cannot be represented by type t.
// It panics if t's Kind is not Complex64 or Complex128.
OverflowComplex(x complex128) bool
return yield.InCount == 2 && yield.OutCount == 1 && yield.Out(0).Kind() == abi.Bool
}
+func (t *rtype) Fields() iter.Seq[StructField] {
+ if t.Kind() != Struct {
+ panic("reflect: Fields of non-struct type " + t.String())
+ }
+ return func(yield func(StructField) bool) {
+ for i := range t.NumField() {
+ if !yield(t.Field(i)) {
+ return
+ }
+ }
+ }
+}
+
+func (t *rtype) Methods() iter.Seq[Method] {
+ return func(yield func(Method) bool) {
+ for i := range t.NumMethod() {
+ if !yield(t.Method(i)) {
+ return
+ }
+ }
+ }
+}
+
+func (t *rtype) Ins() iter.Seq[Type] {
+ if t.Kind() != Func {
+ panic("reflect: Ins of non-func type " + t.String())
+ }
+ return func(yield func(Type) bool) {
+ for i := range t.NumIn() {
+ if !yield(t.In(i)) {
+ return
+ }
+ }
+ }
+}
+
+func (t *rtype) Outs() iter.Seq[Type] {
+ if t.Kind() != Func {
+ panic("reflect: Outs of non-func type " + t.String())
+ }
+ return func(yield func(Type) bool) {
+ for i := range t.NumOut() {
+ if !yield(t.Out(i)) {
+ return
+ }
+ }
+ }
+}
+
// add returns p+x.
//
// The whySafe string is ignored, so that the function still inlines
"internal/goarch"
"internal/strconv"
"internal/unsafeheader"
+ "iter"
"math"
"runtime"
"unsafe"
panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()})
}
+// Fields returns an iterator over each [StructField] of v along with its [Value].
+//
+// The sequence is equivalent to calling [Value.Field] successively
+// for each index i in the range [0, NumField()).
+//
+// It panics if v's Kind is not Struct.
+func (v Value) Fields() iter.Seq2[StructField, Value] {
+ t := v.Type()
+ if t.Kind() != Struct {
+ panic("reflect: Fields of non-struct type " + t.String())
+ }
+ return func(yield func(StructField, Value) bool) {
+ for i := range v.NumField() {
+ if !yield(t.Field(i), v.Field(i)) {
+ return
+ }
+ }
+ }
+}
+
+// Methods returns an iterator over each [Method] of v along with the corresponding
+// method [Value]; this is a function with v bound as the receiver. As such, the
+// receiver shouldn't be included in the arguments to [Value.Call].
+//
+// The sequence is equivalent to calling [Value.Method] successively
+// for each index i in the range [0, NumMethod()).
+//
+// Methods panics if v is a nil interface value.
+//
+// Calling this method will force the linker to retain all exported methods in all packages.
+// This may make the executable binary larger but will not affect execution time.
+func (v Value) Methods() iter.Seq2[Method, Value] {
+ return func(yield func(Method, Value) bool) {
+ rtype := v.Type()
+ for i := range v.NumMethod() {
+ if !yield(rtype.Method(i), v.Method(i)) {
+ return
+ }
+ }
+ }
+}
+
// StringHeader is the runtime representation of a string.
// It cannot be used safely or portably and its representation may
// change in a later release.
return v.IsNil() || v.Elem().Comparable()
case Struct:
- for i := 0; i < v.NumField(); i++ {
- if !v.Field(i).Comparable() {
+ for _, value := range v.Fields() {
+ if !value.Comparable() {
return false
}
}