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")
458 fl := flag(Func) << flagKindShift
459 if p.pkgPath != nil {
460 m.PkgPath = *p.pkgPath
463 mt := toCommonType(p.typ)
465 x := new(unsafe.Pointer)
467 m.Func = Value{mt, unsafe.Pointer(x), fl|flagIndir}
472 func (t *uncommonType) NumMethod() int {
476 return len(t.methods)
479 func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
484 for i := range t.methods {
486 if p.name != nil && *p.name == name {
487 return t.Method(i), true
493 // TODO(rsc): 6g supplies these, but they are not
494 // as efficient as they could be: they have commonType
495 // as the receiver instead of *commonType.
496 func (t *commonType) NumMethod() int {
497 if t.Kind() == Interface {
498 tt := (*interfaceType)(unsafe.Pointer(t))
499 return tt.NumMethod()
501 return t.uncommonType.NumMethod()
504 func (t *commonType) Method(i int) (m Method) {
505 if t.Kind() == Interface {
506 tt := (*interfaceType)(unsafe.Pointer(t))
509 return t.uncommonType.Method(i)
512 func (t *commonType) MethodByName(name string) (m Method, ok bool) {
513 if t.Kind() == Interface {
514 tt := (*interfaceType)(unsafe.Pointer(t))
515 return tt.MethodByName(name)
517 return t.uncommonType.MethodByName(name)
520 func (t *commonType) PkgPath() string {
521 return t.uncommonType.PkgPath()
524 func (t *commonType) Name() string {
525 return t.uncommonType.Name()
528 func (t *commonType) ChanDir() ChanDir {
529 if t.Kind() != Chan {
530 panic("reflect: ChanDir of non-chan type")
532 tt := (*chanType)(unsafe.Pointer(t))
533 return ChanDir(tt.dir)
536 func (t *commonType) IsVariadic() bool {
537 if t.Kind() != Func {
538 panic("reflect: IsVariadic of non-func type")
540 tt := (*funcType)(unsafe.Pointer(t))
544 func (t *commonType) Elem() Type {
547 tt := (*arrayType)(unsafe.Pointer(t))
548 return toType(tt.elem)
550 tt := (*chanType)(unsafe.Pointer(t))
551 return toType(tt.elem)
553 tt := (*mapType)(unsafe.Pointer(t))
554 return toType(tt.elem)
556 tt := (*ptrType)(unsafe.Pointer(t))
557 return toType(tt.elem)
559 tt := (*sliceType)(unsafe.Pointer(t))
560 return toType(tt.elem)
562 panic("reflect; Elem of invalid type")
565 func (t *commonType) Field(i int) StructField {
566 if t.Kind() != Struct {
567 panic("reflect: Field of non-struct type")
569 tt := (*structType)(unsafe.Pointer(t))
573 func (t *commonType) FieldByIndex(index []int) StructField {
574 if t.Kind() != Struct {
575 panic("reflect: FieldByIndex of non-struct type")
577 tt := (*structType)(unsafe.Pointer(t))
578 return tt.FieldByIndex(index)
581 func (t *commonType) FieldByName(name string) (StructField, bool) {
582 if t.Kind() != Struct {
583 panic("reflect: FieldByName of non-struct type")
585 tt := (*structType)(unsafe.Pointer(t))
586 return tt.FieldByName(name)
589 func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool) {
590 if t.Kind() != Struct {
591 panic("reflect: FieldByNameFunc of non-struct type")
593 tt := (*structType)(unsafe.Pointer(t))
594 return tt.FieldByNameFunc(match)
597 func (t *commonType) In(i int) Type {
598 if t.Kind() != Func {
599 panic("reflect: In of non-func type")
601 tt := (*funcType)(unsafe.Pointer(t))
602 return toType(tt.in[i])
605 func (t *commonType) Key() Type {
607 panic("reflect: Key of non-map type")
609 tt := (*mapType)(unsafe.Pointer(t))
610 return toType(tt.key)
613 func (t *commonType) Len() int {
614 if t.Kind() != Array {
615 panic("reflect: Len of non-array type")
617 tt := (*arrayType)(unsafe.Pointer(t))
621 func (t *commonType) NumField() int {
622 if t.Kind() != Struct {
623 panic("reflect: NumField of non-struct type")
625 tt := (*structType)(unsafe.Pointer(t))
626 return len(tt.fields)
629 func (t *commonType) NumIn() int {
630 if t.Kind() != Func {
631 panic("reflect; NumIn of non-func type")
633 tt := (*funcType)(unsafe.Pointer(t))
637 func (t *commonType) NumOut() int {
638 if t.Kind() != Func {
639 panic("reflect; NumOut of non-func type")
641 tt := (*funcType)(unsafe.Pointer(t))
645 func (t *commonType) Out(i int) Type {
646 if t.Kind() != Func {
647 panic("reflect: Out of non-func type")
649 tt := (*funcType)(unsafe.Pointer(t))
650 return toType(tt.out[i])
653 func (d ChanDir) String() string {
662 return "ChanDir" + strconv.Itoa(int(d))
665 // Method returns the i'th method in the type's method set.
666 func (t *interfaceType) Method(i int) (m Method) {
667 if i < 0 || i >= len(t.methods) {
672 if p.pkgPath != nil {
673 m.PkgPath = *p.pkgPath
675 m.Type = toType(p.typ)
680 // NumMethod returns the number of interface methods in the type's method set.
681 func (t *interfaceType) NumMethod() int { return len(t.methods) }
683 // MethodByName method with the given name in the type's method set.
684 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
689 for i := range t.methods {
692 return t.Method(i), true
698 type StructField struct {
699 PkgPath string // empty for uppercase Name
708 // A StructTag is the tag string in a struct field.
710 // By convention, tag strings are a concatenation of
711 // optionally space-separated key:"value" pairs.
712 // Each key is a non-empty string consisting of non-control
713 // characters other than space (U+0020 ' '), quote (U+0022 '"'),
714 // and colon (U+003A ':'). Each value is quoted using U+0022 '"'
715 // characters and Go string literal syntax.
716 type StructTag string
718 // Get returns the value associated with key in the tag string.
719 // If there is no such key in the tag, Get returns the empty string.
720 // If the tag does not have the conventional format, the value
721 // returned by Get is unspecified.
722 func (tag StructTag) Get(key string) string {
724 // skip leading space
726 for i < len(tag) && tag[i] == ' ' {
735 // a space or a quote is a syntax error
737 for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
740 if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
743 name := string(tag[:i])
746 // scan quoted string to find value
748 for i < len(tag) && tag[i] != '"' {
757 qvalue := string(tag[:i+1])
761 value, _ := strconv.Unquote(qvalue)
768 // Field returns the i'th struct field.
769 func (t *structType) Field(i int) (f StructField) {
770 if i < 0 || i >= len(t.fields) {
774 f.Type = toType(p.typ)
785 if p.pkgPath != nil {
786 f.PkgPath = *p.pkgPath
789 f.Tag = StructTag(*p.tag)
796 // TODO(gri): Should there be an error/bool indicator if the index
797 // is wrong for FieldByIndex?
799 // FieldByIndex returns the nested field corresponding to index.
800 func (t *structType) FieldByIndex(index []int) (f StructField) {
801 f.Type = Type(t.toType())
802 for i, x := range index {
805 if ft.Kind() == Ptr && ft.Elem().Kind() == Struct {
815 const inf = 1 << 30 // infinity - no struct has that many nesting levels
817 func (t *structType) fieldByNameFunc(match func(string) bool, mark map[*structType]bool, depth int) (ff StructField, fd int) {
818 fd = inf // field depth
821 // Struct already seen.
826 var fi int // field index
827 n := 0 // number of matching fields at depth fd
829 for i := range t.fields {
834 // Matching top-level field.
838 if ft.Kind() == Ptr {
842 case match(ft.Name()):
843 // Matching anonymous top-level field.
846 // No top-level field yet; look inside nested structs.
847 if ft.Kind() == Struct {
848 st := (*structType)(unsafe.Pointer(ft.(*commonType)))
849 f, d = st.fieldByNameFunc(match, mark, depth+1)
856 // Found field at shallower depth.
860 // More than one matching field at the same depth (or d, fd == inf).
861 // Same as no field found at this depth.
864 // Impossible to find a field at lower depth.
871 // Found matching field.
872 if depth >= len(ff.Index) {
873 ff.Index = make([]int, depth+1)
875 if len(ff.Index) > 1 {
879 // None or more than one matching field found.
887 // FieldByName returns the struct field with the given name
888 // and a boolean to indicate if the field was found.
889 func (t *structType) FieldByName(name string) (f StructField, present bool) {
890 return t.FieldByNameFunc(func(s string) bool { return s == name })
893 // FieldByNameFunc returns the struct field with a name that satisfies the
894 // match function and a boolean to indicate if the field was found.
895 func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, present bool) {
896 if ff, fd := t.fieldByNameFunc(match, make(map[*structType]bool), 0); fd < inf {
897 ff.Index = ff.Index[0 : fd+1]
898 f, present = ff, true
903 // Convert runtime type to reflect type.
904 func toCommonType(p *runtime.Type) *commonType {
908 x := unsafe.Pointer(p)
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 return t.(*commonType).ptrTo()
973 func (ct *commonType) ptrTo() *commonType {
974 if p := ct.ptrToThis; p != nil {
975 return toCommonType(p)
978 // Otherwise, synthesize one.
979 // This only happens for pointers with no methods.
980 // We keep the mapping in a map on the side, because
981 // this operation is rare and a separate map lets us keep
982 // the type structures in read-only memory.
984 if m := ptrMap.m; m != nil {
985 if p := m[ct]; p != nil {
993 ptrMap.m = make(map[*commonType]*ptrType)
997 // some other goroutine won the race and created it
1002 rt := (*runtime.Type)(unsafe.Pointer(ct))
1004 rp := new(runtime.PtrType)
1006 // initialize p using *byte's ptrType as a prototype.
1007 // have to do assignment as ptrType, not runtime.PtrType,
1008 // in order to write to unexported fields.
1009 p = (*ptrType)(unsafe.Pointer(rp))
1010 bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType)))
1013 s := "*" + *ct.string
1016 // For the type structures linked into the binary, the
1017 // compiler provides a good hash of the string.
1018 // Create a good hash for the new string by using
1019 // the FNV-1 hash's mixing function to combine the
1020 // old hash and the new "*".
1021 p.hash = ct.hash*16777619 ^ '*'
1023 p.uncommonType = nil
1025 p.elem = (*runtime.Type)(unsafe.Pointer(ct))
1029 return &p.commonType
1032 func (t *commonType) Implements(u Type) bool {
1034 panic("reflect: nil type passed to Type.Implements")
1036 if u.Kind() != Interface {
1037 panic("reflect: non-interface type passed to Type.Implements")
1039 return implements(u.(*commonType), t)
1042 func (t *commonType) AssignableTo(u Type) bool {
1044 panic("reflect: nil type passed to Type.AssignableTo")
1046 uu := u.(*commonType)
1047 return directlyAssignable(uu, t) || implements(uu, t)
1050 // implements returns true if the type V implements the interface type T.
1051 func implements(T, V *commonType) bool {
1052 if T.Kind() != Interface {
1055 t := (*interfaceType)(unsafe.Pointer(T))
1056 if len(t.methods) == 0 {
1060 // The same algorithm applies in both cases, but the
1061 // method tables for an interface type and a concrete type
1062 // are different, so the code is duplicated.
1063 // In both cases the algorithm is a linear scan over the two
1064 // lists - T's methods and V's methods - simultaneously.
1065 // Since method tables are stored in a unique sorted order
1066 // (alphabetical, with no duplicate method names), the scan
1067 // through V's methods must hit a match for each of T's
1068 // methods along the way, or else V does not implement T.
1069 // This lets us run the scan in overall linear time instead of
1070 // the quadratic time a naive search would require.
1071 // See also ../runtime/iface.c.
1072 if V.Kind() == Interface {
1073 v := (*interfaceType)(unsafe.Pointer(V))
1075 for j := 0; j < len(v.methods); j++ {
1078 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() {
1079 if i++; i >= len(t.methods) {
1092 for j := 0; j < len(v.methods); j++ {
1095 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() {
1096 if i++; i >= len(t.methods) {
1104 // directlyAssignable returns true if a value x of type V can be directly
1105 // assigned (using memmove) to a value of type T.
1106 // http://golang.org/doc/go_spec.html#Assignability
1107 // Ignoring the interface rules (implemented elsewhere)
1108 // and the ideal constant rules (no ideal constants at run time).
1109 func directlyAssignable(T, V *commonType) bool {
1110 // x's type V is identical to T?
1115 // Otherwise at least one of T and V must be unnamed
1116 // and they must have the same kind.
1117 if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
1121 // x's type T and V have identical underlying types.
1122 // Since at least one is unnamed, only the composite types
1123 // need to be considered.
1126 return T.Elem() == V.Elem() && T.Len() == V.Len()
1130 // x is a bidirectional channel value, T is a channel type,
1131 // and x's type V and T have identical element types.
1132 if V.ChanDir() == BothDir && T.Elem() == V.Elem() {
1136 // Otherwise continue test for identical underlying type.
1137 return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem()
1140 t := (*funcType)(unsafe.Pointer(T))
1141 v := (*funcType)(unsafe.Pointer(V))
1142 if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) {
1145 for i, typ := range t.in {
1150 for i, typ := range t.out {
1151 if typ != v.out[i] {
1158 t := (*interfaceType)(unsafe.Pointer(T))
1159 v := (*interfaceType)(unsafe.Pointer(V))
1160 if len(t.methods) == 0 && len(v.methods) == 0 {
1163 // Might have the same methods but still
1164 // need a run time conversion.
1168 return T.Key() == V.Key() && T.Elem() == V.Elem()
1171 return T.Elem() == V.Elem()
1174 t := (*structType)(unsafe.Pointer(T))
1175 v := (*structType)(unsafe.Pointer(V))
1176 if len(t.fields) != len(v.fields) {
1179 for i := range t.fields {
1182 if tf.name != vf.name || tf.pkgPath != vf.pkgPath ||
1183 tf.typ != vf.typ || tf.tag != vf.tag || tf.offset != vf.offset {