1 // Copyright 2009 The Go Authors. 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.
5 // Package reflect implements run-time reflection, allowing a program to
6 // manipulate objects with arbitrary types. The typical use is to take a value
7 // with static type interface{} and extract its dynamic type information by
8 // calling TypeOf, which returns a Type.
10 // A call to ValueOf returns a Value representing the run-time data.
11 // Zero takes a Type and returns a Value representing a zero value
14 // See "The Laws of Reflection" for an introduction to reflection in Go:
15 // http://blog.golang.org/2011/09/laws-of-reflection.html
25 // Type is the representation of a Go type.
27 // Not all methods apply to all kinds of types. Restrictions,
28 // if any, are noted in the documentation for each method.
29 // Use the Kind method to find out the kind of type before
30 // calling kind-specific methods. Calling a method
31 // inappropriate to the kind of type causes a run-time panic.
33 // Methods applicable to all types.
35 // Align returns the alignment in bytes of a value of
36 // this type when allocated in memory.
39 // FieldAlign returns the alignment in bytes of a value of
40 // this type when used as a field in a struct.
43 // Method returns the i'th method in the type's method set.
44 // It panics if i is not in the range [0, NumMethod()).
46 // For a non-interface type T or *T, the returned Method's Type and Func
47 // fields describe a function whose first argument is the receiver.
49 // For an interface type, the returned Method's Type field gives the
50 // method signature, without a receiver, and the Func field is nil.
53 // MethodByName returns the method with that name in the type's
54 // method set and a boolean indicating if the method was found.
56 // For a non-interface type T or *T, the returned Method's Type and Func
57 // fields describe a function whose first argument is the receiver.
59 // For an interface type, the returned Method's Type field gives the
60 // method signature, without a receiver, and the Func field is nil.
61 MethodByName(string) (Method, bool)
63 // NumMethod returns the number of methods in the type's method set.
66 // Name returns the type's name within its package.
67 // It returns an empty string for unnamed types.
70 // PkgPath returns the type's package path.
71 // The package path is a full package import path like "encoding/base64".
72 // PkgPath returns an empty string for unnamed types.
75 // Size returns the number of bytes needed to store
76 // a value of the given type; it is analogous to unsafe.Sizeof.
79 // String returns a string representation of the type.
80 // The string representation may use shortened package names
81 // (e.g., base64 instead of "encoding/base64") and is not
82 // guaranteed to be unique among types. To test for equality,
83 // compare the Types directly.
86 // Kind returns the specific kind of this type.
89 // Implements returns true if the type implements the interface type u.
90 Implements(u Type) bool
92 // AssignableTo returns true if a value of the type is assignable to type u.
93 AssignableTo(u Type) bool
95 // Methods applicable only to some types, depending on Kind.
96 // The methods allowed for each kind are:
98 // Int*, Uint*, Float*, Complex*: Bits
100 // Chan: ChanDir, Elem
101 // Func: In, NumIn, Out, NumOut, IsVariadic.
105 // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
107 // Bits returns the size of the type in bits.
108 // It panics if the type's Kind is not one of the
109 // sized or unsized Int, Uint, Float, or Complex kinds.
112 // ChanDir returns a channel type's direction.
113 // It panics if the type's Kind is not Chan.
116 // IsVariadic returns true if a function type's final input parameter
117 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
118 // implicit actual type []T.
120 // For concreteness, if t represents func(x int, y ... float64), then
123 // t.In(0) is the reflect.Type for "int"
124 // t.In(1) is the reflect.Type for "[]float64"
125 // t.IsVariadic() == true
127 // IsVariadic panics if the type's Kind is not Func.
130 // Elem returns a type's element type.
131 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
134 // Field returns a struct type's i'th field.
135 // It panics if the type's Kind is not Struct.
136 // It panics if i is not in the range [0, NumField()).
137 Field(i int) StructField
139 // FieldByIndex returns the nested field corresponding
140 // to the index sequence. It is equivalent to calling Field
141 // successively for each index i.
142 // It panics if the type's Kind is not Struct.
143 FieldByIndex(index []int) StructField
145 // FieldByName returns the struct field with the given name
146 // and a boolean indicating if the field was found.
147 FieldByName(name string) (StructField, bool)
149 // FieldByNameFunc returns the first struct field with a name
150 // that satisfies the match function and a boolean indicating if
151 // the field was found.
152 FieldByNameFunc(match func(string) bool) (StructField, bool)
154 // In returns the type of a function type's i'th input parameter.
155 // It panics if the type's Kind is not Func.
156 // It panics if i is not in the range [0, NumIn()).
159 // Key returns a map type's key type.
160 // It panics if the type's Kind is not Map.
163 // Len returns an array type's length.
164 // It panics if the type's Kind is not Array.
167 // NumField returns a struct type's field count.
168 // It panics if the type's Kind is not Struct.
171 // NumIn returns a function type's input parameter count.
172 // It panics if the type's Kind is not Func.
175 // NumOut returns a function type's output parameter count.
176 // It panics if the type's Kind is not Func.
179 // Out returns the type of a function type's i'th output parameter.
180 // It panics if the type's Kind is not Func.
181 // It panics if i is not in the range [0, NumOut()).
184 runtimeType() *runtime.Type
186 uncommon() *uncommonType
189 // A Kind represents the specific kind of type that a Type represents.
190 // The zero Kind is not a valid kind.
224 * Copy of data structures from ../runtime/type.go.
225 * For comments, see the ones in that file.
227 * These data structures are known to the compiler and the runtime.
229 * Putting these types in runtime instead of reflect means that
230 * reflect doesn't need to be autolinked into every binary, which
231 * simplifies bootstrapping and package dependencies.
232 * Unfortunately, it also means that reflect needs its own
233 * copy in order to access the private fields.
236 // commonType is the common implementation of most values.
237 // It is embedded in other, public struct types, but always
238 // with a unique tag like `reflect:"array"` or `reflect:"ptr"`
239 // so that code cannot convert from, say, *arrayType to *ptrType.
241 type commonType struct {
247 hashfn func(unsafe.Pointer, uintptr)
248 equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr)
251 ptrToThis *runtime.Type
262 type uncommonType struct {
268 // ChanDir represents a channel type's direction.
272 RecvDir ChanDir = 1 << iota
274 BothDir = RecvDir | SendDir
277 // arrayType represents a fixed array type.
278 type arrayType struct {
279 commonType `reflect:"array"`
285 // chanType represents a channel type.
286 type chanType struct {
287 commonType `reflect:"chan"`
292 // funcType represents a function type.
293 type funcType struct {
294 commonType `reflect:"func"`
300 // imethod represents a method on an interface type
301 type imethod struct {
307 // interfaceType represents an interface type.
308 type interfaceType struct {
309 commonType `reflect:"interface"`
313 // mapType represents a map type.
314 type mapType struct {
315 commonType `reflect:"map"`
320 // ptrType represents a pointer type.
321 type ptrType struct {
322 commonType `reflect:"ptr"`
326 // sliceType represents a slice type.
327 type sliceType struct {
328 commonType `reflect:"slice"`
333 type structField struct {
341 // structType represents a struct type.
342 type structType struct {
343 commonType `reflect:"struct"`
348 * The compiler knows the exact layout of all the data structures above.
349 * The compiler does not know about the data structures and methods below.
352 // Method represents a single method.
354 PkgPath string // empty for uppercase Name
361 // High bit says whether type has
362 // embedded pointers,to help garbage collector.
363 const kindMask = 0x7f
365 func (k Kind) String() string {
366 if int(k) < len(kindNames) {
369 return "kind" + strconv.Itoa(int(k))
372 var kindNames = []string{
388 Complex64: "complex64",
389 Complex128: "complex128",
393 Interface: "interface",
399 UnsafePointer: "unsafe.Pointer",
402 func (t *uncommonType) uncommon() *uncommonType {
406 func (t *uncommonType) PkgPath() string {
407 if t == nil || t.pkgPath == nil {
413 func (t *uncommonType) Name() string {
414 if t == nil || t.name == nil {
420 func (t *commonType) toType() Type {
424 return canonicalize(t)
427 func (t *commonType) String() string { return *t.string }
429 func (t *commonType) Size() uintptr { return t.size }
431 func (t *commonType) Bits() int {
433 panic("reflect: Bits of nil Type")
436 if k < Int || k > Complex128 {
437 panic("reflect: Bits of non-arithmetic Type " + t.String())
439 return int(t.size) * 8
442 func (t *commonType) Align() int { return int(t.align) }
444 func (t *commonType) FieldAlign() int { return int(t.fieldAlign) }
446 func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) }
448 func (t *commonType) common() *commonType { return t }
450 func (t *uncommonType) Method(i int) (m Method) {
451 if t == nil || i < 0 || i >= len(t.methods) {
452 panic("reflect: Method index out of range")
459 if p.pkgPath != nil {
460 m.PkgPath = *p.pkgPath
463 m.Type = toType(p.typ)
464 x := new(unsafe.Pointer)
466 m.Func = valueFromIword(flag, m.Type, iword(uintptr(unsafe.Pointer(x))))
471 func (t *uncommonType) NumMethod() int {
475 return len(t.methods)
478 func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
483 for i := range t.methods {
485 if p.name != nil && *p.name == name {
486 return t.Method(i), true
492 // TODO(rsc): 6g supplies these, but they are not
493 // as efficient as they could be: they have commonType
494 // as the receiver instead of *commonType.
495 func (t *commonType) NumMethod() int {
496 if t.Kind() == Interface {
497 tt := (*interfaceType)(unsafe.Pointer(t))
498 return tt.NumMethod()
500 return t.uncommonType.NumMethod()
503 func (t *commonType) Method(i int) (m Method) {
504 if t.Kind() == Interface {
505 tt := (*interfaceType)(unsafe.Pointer(t))
508 return t.uncommonType.Method(i)
511 func (t *commonType) MethodByName(name string) (m Method, ok bool) {
512 if t.Kind() == Interface {
513 tt := (*interfaceType)(unsafe.Pointer(t))
514 return tt.MethodByName(name)
516 return t.uncommonType.MethodByName(name)
519 func (t *commonType) PkgPath() string {
520 return t.uncommonType.PkgPath()
523 func (t *commonType) Name() string {
524 return t.uncommonType.Name()
527 func (t *commonType) ChanDir() ChanDir {
528 if t.Kind() != Chan {
529 panic("reflect: ChanDir of non-chan type")
531 tt := (*chanType)(unsafe.Pointer(t))
532 return ChanDir(tt.dir)
535 func (t *commonType) IsVariadic() bool {
536 if t.Kind() != Func {
537 panic("reflect: IsVariadic of non-func type")
539 tt := (*funcType)(unsafe.Pointer(t))
543 func (t *commonType) Elem() Type {
546 tt := (*arrayType)(unsafe.Pointer(t))
547 return toType(tt.elem)
549 tt := (*chanType)(unsafe.Pointer(t))
550 return toType(tt.elem)
552 tt := (*mapType)(unsafe.Pointer(t))
553 return toType(tt.elem)
555 tt := (*ptrType)(unsafe.Pointer(t))
556 return toType(tt.elem)
558 tt := (*sliceType)(unsafe.Pointer(t))
559 return toType(tt.elem)
561 panic("reflect; Elem of invalid type")
564 func (t *commonType) Field(i int) StructField {
565 if t.Kind() != Struct {
566 panic("reflect: Field of non-struct type")
568 tt := (*structType)(unsafe.Pointer(t))
572 func (t *commonType) FieldByIndex(index []int) StructField {
573 if t.Kind() != Struct {
574 panic("reflect: FieldByIndex of non-struct type")
576 tt := (*structType)(unsafe.Pointer(t))
577 return tt.FieldByIndex(index)
580 func (t *commonType) FieldByName(name string) (StructField, bool) {
581 if t.Kind() != Struct {
582 panic("reflect: FieldByName of non-struct type")
584 tt := (*structType)(unsafe.Pointer(t))
585 return tt.FieldByName(name)
588 func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool) {
589 if t.Kind() != Struct {
590 panic("reflect: FieldByNameFunc of non-struct type")
592 tt := (*structType)(unsafe.Pointer(t))
593 return tt.FieldByNameFunc(match)
596 func (t *commonType) In(i int) Type {
597 if t.Kind() != Func {
598 panic("reflect: In of non-func type")
600 tt := (*funcType)(unsafe.Pointer(t))
601 return toType(tt.in[i])
604 func (t *commonType) Key() Type {
606 panic("reflect: Key of non-map type")
608 tt := (*mapType)(unsafe.Pointer(t))
609 return toType(tt.key)
612 func (t *commonType) Len() int {
613 if t.Kind() != Array {
614 panic("reflect: Len of non-array type")
616 tt := (*arrayType)(unsafe.Pointer(t))
620 func (t *commonType) NumField() int {
621 if t.Kind() != Struct {
622 panic("reflect: NumField of non-struct type")
624 tt := (*structType)(unsafe.Pointer(t))
625 return len(tt.fields)
628 func (t *commonType) NumIn() int {
629 if t.Kind() != Func {
630 panic("reflect; NumIn of non-func type")
632 tt := (*funcType)(unsafe.Pointer(t))
636 func (t *commonType) NumOut() int {
637 if t.Kind() != Func {
638 panic("reflect; NumOut of non-func type")
640 tt := (*funcType)(unsafe.Pointer(t))
644 func (t *commonType) Out(i int) Type {
645 if t.Kind() != Func {
646 panic("reflect: Out of non-func type")
648 tt := (*funcType)(unsafe.Pointer(t))
649 return toType(tt.out[i])
652 func (d ChanDir) String() string {
661 return "ChanDir" + strconv.Itoa(int(d))
664 // Method returns the i'th method in the type's method set.
665 func (t *interfaceType) Method(i int) (m Method) {
666 if i < 0 || i >= len(t.methods) {
671 if p.pkgPath != nil {
672 m.PkgPath = *p.pkgPath
674 m.Type = toType(p.typ)
679 // NumMethod returns the number of interface methods in the type's method set.
680 func (t *interfaceType) NumMethod() int { return len(t.methods) }
682 // MethodByName method with the given name in the type's method set.
683 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
688 for i := range t.methods {
691 return t.Method(i), true
697 type StructField struct {
698 PkgPath string // empty for uppercase Name
707 // A StructTag is the tag string in a struct field.
709 // By convention, tag strings are a concatenation of
710 // optionally space-separated key:"value" pairs.
711 // Each key is a non-empty string consisting of non-control
712 // characters other than space (U+0020 ' '), quote (U+0022 '"'),
713 // and colon (U+003A ':'). Each value is quoted using U+0022 '"'
714 // characters and Go string literal syntax.
715 type StructTag string
717 // Get returns the value associated with key in the tag string.
718 // If there is no such key in the tag, Get returns the empty string.
719 // If the tag does not have the conventional format, the value
720 // returned by Get is unspecified.
721 func (tag StructTag) Get(key string) string {
723 // skip leading space
725 for i < len(tag) && tag[i] == ' ' {
734 // a space or a quote is a syntax error
736 for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
739 if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
742 name := string(tag[:i])
745 // scan quoted string to find value
747 for i < len(tag) && tag[i] != '"' {
756 qvalue := string(tag[:i+1])
760 value, _ := strconv.Unquote(qvalue)
767 // Field returns the i'th struct field.
768 func (t *structType) Field(i int) (f StructField) {
769 if i < 0 || i >= len(t.fields) {
773 f.Type = toType(p.typ)
784 if p.pkgPath != nil {
785 f.PkgPath = *p.pkgPath
788 f.Tag = StructTag(*p.tag)
795 // TODO(gri): Should there be an error/bool indicator if the index
796 // is wrong for FieldByIndex?
798 // FieldByIndex returns the nested field corresponding to index.
799 func (t *structType) FieldByIndex(index []int) (f StructField) {
800 f.Type = Type(t.toType())
801 for i, x := range index {
804 if ft.Kind() == Ptr && ft.Elem().Kind() == Struct {
814 const inf = 1 << 30 // infinity - no struct has that many nesting levels
816 func (t *structType) fieldByNameFunc(match func(string) bool, mark map[*structType]bool, depth int) (ff StructField, fd int) {
817 fd = inf // field depth
820 // Struct already seen.
825 var fi int // field index
826 n := 0 // number of matching fields at depth fd
828 for i := range t.fields {
833 // Matching top-level field.
837 if ft.Kind() == Ptr {
841 case match(ft.Name()):
842 // Matching anonymous top-level field.
845 // No top-level field yet; look inside nested structs.
846 if ft.Kind() == Struct {
847 st := (*structType)(unsafe.Pointer(ft.(*commonType)))
848 f, d = st.fieldByNameFunc(match, mark, depth+1)
855 // Found field at shallower depth.
859 // More than one matching field at the same depth (or d, fd == inf).
860 // Same as no field found at this depth.
863 // Impossible to find a field at lower depth.
870 // Found matching field.
871 if len(ff.Index) <= depth {
872 ff.Index = make([]int, depth+1)
876 // None or more than one matching field found.
884 // FieldByName returns the struct field with the given name
885 // and a boolean to indicate if the field was found.
886 func (t *structType) FieldByName(name string) (f StructField, present bool) {
887 return t.FieldByNameFunc(func(s string) bool { return s == name })
890 // FieldByNameFunc returns the struct field with a name that satisfies the
891 // match function and a boolean to indicate if the field was found.
892 func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, present bool) {
893 if ff, fd := t.fieldByNameFunc(match, make(map[*structType]bool), 0); fd < inf {
894 ff.Index = ff.Index[0 : fd+1]
895 f, present = ff, true
900 // Convert runtime type to reflect type.
901 func toCommonType(p *runtime.Type) *commonType {
905 x := unsafe.Pointer(p)
906 if uintptr(x)&reflectFlags != 0 {
907 panic("reflect: invalid interface value")
909 return (*commonType)(x)
912 // Canonicalize a Type.
913 var canonicalType = make(map[string]Type)
915 var canonicalTypeLock sync.RWMutex
917 func canonicalize(t Type) Type {
923 if u == nil || u.PkgPath() == "" {
926 s = u.PkgPath() + "." + u.Name()
928 canonicalTypeLock.RLock()
929 if r, ok := canonicalType[s]; ok {
930 canonicalTypeLock.RUnlock()
933 canonicalTypeLock.RUnlock()
934 canonicalTypeLock.Lock()
935 if r, ok := canonicalType[s]; ok {
936 canonicalTypeLock.Unlock()
940 canonicalTypeLock.Unlock()
944 func toType(p *runtime.Type) Type {
948 return toCommonType(p).toType()
951 // TypeOf returns the reflection Type of the value in the interface{}.
952 func TypeOf(i interface{}) Type {
953 eface := *(*emptyInterface)(unsafe.Pointer(&i))
954 return toType(eface.typ)
957 // ptrMap is the cache for PtrTo.
960 m map[*commonType]*ptrType
963 func (t *commonType) runtimeType() *runtime.Type {
964 return (*runtime.Type)(unsafe.Pointer(t))
967 // PtrTo returns the pointer type with element t.
968 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
969 func PtrTo(t Type) Type {
970 // If t records its pointer-to type, use it.
971 ct := t.(*commonType)
972 if p := ct.ptrToThis; p != nil {
976 // Otherwise, synthesize one.
977 // This only happens for pointers with no methods.
978 // We keep the mapping in a map on the side, because
979 // this operation is rare and a separate map lets us keep
980 // the type structures in read-only memory.
982 if m := ptrMap.m; m != nil {
983 if p := m[ct]; p != nil {
985 return p.commonType.toType()
991 ptrMap.m = make(map[*commonType]*ptrType)
995 // some other goroutine won the race and created it
1000 rt := (*runtime.Type)(unsafe.Pointer(ct))
1002 rp := new(runtime.PtrType)
1004 // initialize p using *byte's ptrType as a prototype.
1005 // have to do assignment as ptrType, not runtime.PtrType,
1006 // in order to write to unexported fields.
1007 p = (*ptrType)(unsafe.Pointer(rp))
1008 bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType)))
1011 s := "*" + *ct.string
1014 // For the type structures linked into the binary, the
1015 // compiler provides a good hash of the string.
1016 // Create a good hash for the new string by using
1017 // the FNV-1 hash's mixing function to combine the
1018 // old hash and the new "*".
1019 p.hash = ct.hash*16777619 ^ '*'
1021 p.uncommonType = nil
1023 p.elem = (*runtime.Type)(unsafe.Pointer(ct))
1027 return p.commonType.toType()
1030 func (t *commonType) Implements(u Type) bool {
1032 panic("reflect: nil type passed to Type.Implements")
1034 if u.Kind() != Interface {
1035 panic("reflect: non-interface type passed to Type.Implements")
1037 return implements(u.(*commonType), t)
1040 func (t *commonType) AssignableTo(u Type) bool {
1042 panic("reflect: nil type passed to Type.AssignableTo")
1044 uu := u.(*commonType)
1045 return directlyAssignable(uu, t) || implements(uu, t)
1048 // implements returns true if the type V implements the interface type T.
1049 func implements(T, V *commonType) bool {
1050 if T.Kind() != Interface {
1053 t := (*interfaceType)(unsafe.Pointer(T))
1054 if len(t.methods) == 0 {
1058 // The same algorithm applies in both cases, but the
1059 // method tables for an interface type and a concrete type
1060 // are different, so the code is duplicated.
1061 // In both cases the algorithm is a linear scan over the two
1062 // lists - T's methods and V's methods - simultaneously.
1063 // Since method tables are stored in a unique sorted order
1064 // (alphabetical, with no duplicate method names), the scan
1065 // through V's methods must hit a match for each of T's
1066 // methods along the way, or else V does not implement T.
1067 // This lets us run the scan in overall linear time instead of
1068 // the quadratic time a naive search would require.
1069 // See also ../runtime/iface.c.
1070 if V.Kind() == Interface {
1071 v := (*interfaceType)(unsafe.Pointer(V))
1073 for j := 0; j < len(v.methods); j++ {
1076 if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.typ).common() == toType(tm.typ).common() {
1077 if i++; i >= len(t.methods) {
1090 for j := 0; j < len(v.methods); j++ {
1093 if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.mtyp).common() == toType(tm.typ).common() {
1094 if i++; i >= len(t.methods) {
1102 // directlyAssignable returns true if a value x of type V can be directly
1103 // assigned (using memmove) to a value of type T.
1104 // http://golang.org/doc/go_spec.html#Assignability
1105 // Ignoring the interface rules (implemented elsewhere)
1106 // and the ideal constant rules (no ideal constants at run time).
1107 func directlyAssignable(T, V *commonType) bool {
1108 // x's type V is identical to T?
1113 // Otherwise at least one of T and V must be unnamed
1114 // and they must have the same kind.
1115 if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
1119 // x's type T and V have identical underlying types.
1120 // Since at least one is unnamed, only the composite types
1121 // need to be considered.
1124 return T.Elem() == V.Elem() && T.Len() == V.Len()
1128 // x is a bidirectional channel value, T is a channel type,
1129 // and x's type V and T have identical element types.
1130 if V.ChanDir() == BothDir && T.Elem() == V.Elem() {
1134 // Otherwise continue test for identical underlying type.
1135 return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem()
1138 t := (*funcType)(unsafe.Pointer(T))
1139 v := (*funcType)(unsafe.Pointer(V))
1140 if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) {
1143 for i, typ := range t.in {
1148 for i, typ := range t.out {
1149 if typ != v.out[i] {
1156 t := (*interfaceType)(unsafe.Pointer(T))
1157 v := (*interfaceType)(unsafe.Pointer(V))
1158 if len(t.methods) == 0 && len(v.methods) == 0 {
1161 // Might have the same methods but still
1162 // need a run time conversion.
1166 return T.Key() == V.Key() && T.Elem() == V.Elem()
1169 return T.Elem() == V.Elem()
1172 t := (*structType)(unsafe.Pointer(T))
1173 v := (*structType)(unsafe.Pointer(V))
1174 if len(t.fields) != len(v.fields) {
1177 for i := range t.fields {
1180 if tf.name != vf.name || tf.pkgPath != vf.pkgPath ||
1181 tf.typ != vf.typ || tf.tag != vf.tag || tf.offset != vf.offset {