| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // The reflect package implements run-time reflection, allowing a program to |
| // manipulate objects with arbitrary types. The typical use is to take a |
| // value with static type interface{} and extract its dynamic type |
| // information by calling Typeof, which returns an object with interface |
| // type Type. That contains a pointer to a struct of type *StructType, |
| // *IntType, etc. representing the details of the underlying type. A type |
| // switch or type assertion can reveal which. |
| // |
| // A call to NewValue creates a Value representing the run-time data; it |
| // contains a *StructValue, *IntValue, etc. MakeZero takes a Type and |
| // returns a Value representing a zero value for that type. |
| package reflect |
| |
| import ( |
| "runtime" |
| "strconv" |
| "sync" |
| "unsafe" |
| ) |
| |
| /* |
| * Copy of data structures from ../runtime/type.go. |
| * For comments, see the ones in that file. |
| * |
| * These data structures are known to the compiler and the runtime. |
| * |
| * Putting these types in runtime instead of reflect means that |
| * reflect doesn't need to be autolinked into every binary, which |
| * simplifies bootstrapping and package dependencies. |
| * Unfortunately, it also means that reflect needs its own |
| * copy in order to access the private fields. |
| */ |
| |
| // commonType is the common implementation of most values. |
| // It is embedded in other, public struct types, but always |
| // with a unique tag like "uint" or "float" so that the client cannot |
| // convert from, say, *UintType to *FloatType. |
| |
| type commonType struct { |
| size uintptr |
| hash uint32 |
| alg uint8 |
| align uint8 |
| fieldAlign uint8 |
| kind uint8 |
| string *string |
| *uncommonType |
| ptrToThis *runtime.Type |
| } |
| |
| type method struct { |
| name *string |
| pkgPath *string |
| mtyp *runtime.Type |
| typ *runtime.Type |
| ifn unsafe.Pointer |
| tfn unsafe.Pointer |
| } |
| |
| type uncommonType struct { |
| name *string |
| pkgPath *string |
| methods []method |
| } |
| |
| // BoolType represents a boolean type. |
| type BoolType struct { |
| commonType "bool" |
| } |
| |
| // FloatType represents a float type. |
| type FloatType struct { |
| commonType "float" |
| } |
| |
| // ComplexType represents a complex type. |
| type ComplexType struct { |
| commonType "complex" |
| } |
| |
| // IntType represents a signed integer type. |
| type IntType struct { |
| commonType "int" |
| } |
| |
| // UintType represents a uint type. |
| type UintType struct { |
| commonType "uint" |
| } |
| |
| // StringType represents a string type. |
| type StringType struct { |
| commonType "string" |
| } |
| |
| // UnsafePointerType represents an unsafe.Pointer type. |
| type UnsafePointerType struct { |
| commonType "unsafe.Pointer" |
| } |
| |
| // ArrayType represents a fixed array type. |
| type ArrayType struct { |
| commonType "array" |
| elem *runtime.Type |
| len uintptr |
| } |
| |
| // ChanDir represents a channel type's direction. |
| type ChanDir int |
| |
| const ( |
| RecvDir ChanDir = 1 << iota |
| SendDir |
| BothDir = RecvDir | SendDir |
| ) |
| |
| // ChanType represents a channel type. |
| type ChanType struct { |
| commonType "chan" |
| elem *runtime.Type |
| dir uintptr |
| } |
| |
| // FuncType represents a function type. |
| type FuncType struct { |
| commonType "func" |
| dotdotdot bool |
| in []*runtime.Type |
| out []*runtime.Type |
| } |
| |
| // Method on interface type |
| type imethod struct { |
| name *string |
| pkgPath *string |
| typ *runtime.Type |
| } |
| |
| // InterfaceType represents an interface type. |
| type InterfaceType struct { |
| commonType "interface" |
| methods []imethod |
| } |
| |
| // MapType represents a map type. |
| type MapType struct { |
| commonType "map" |
| key *runtime.Type |
| elem *runtime.Type |
| } |
| |
| // PtrType represents a pointer type. |
| type PtrType struct { |
| commonType "ptr" |
| elem *runtime.Type |
| } |
| |
| // SliceType represents a slice type. |
| type SliceType struct { |
| commonType "slice" |
| elem *runtime.Type |
| } |
| |
| // arrayOrSliceType is an unexported method that guarantees only |
| // arrays and slices implement ArrayOrSliceType. |
| func (*SliceType) arrayOrSliceType() {} |
| |
| // Struct field |
| type structField struct { |
| name *string |
| pkgPath *string |
| typ *runtime.Type |
| tag *string |
| offset uintptr |
| } |
| |
| // StructType represents a struct type. |
| type StructType struct { |
| commonType "struct" |
| fields []structField |
| } |
| |
| |
| /* |
| * The compiler knows the exact layout of all the data structures above. |
| * The compiler does not know about the data structures and methods below. |
| */ |
| |
| // Method represents a single method. |
| type Method struct { |
| PkgPath string // empty for uppercase Name |
| Name string |
| Type *FuncType |
| Func *FuncValue |
| } |
| |
| // Type is the runtime representation of a Go type. |
| // Every type implements the methods listed here. |
| // Some types implement additional interfaces; |
| // use a type switch to find out what kind of type a Type is. |
| // Each type in a program has a unique Type, so == on Types |
| // corresponds to Go's type equality. |
| type Type interface { |
| // PkgPath returns the type's package path. |
| // The package path is a full package import path like "container/vector". |
| // PkgPath returns an empty string for unnamed types. |
| PkgPath() string |
| |
| // Name returns the type's name within its package. |
| // Name returns an empty string for unnamed types. |
| Name() string |
| |
| // String returns a string representation of the type. |
| // The string representation may use shortened package names |
| // (e.g., vector instead of "container/vector") and is not |
| // guaranteed to be unique among types. To test for equality, |
| // compare the Types directly. |
| String() string |
| |
| // Size returns the number of bytes needed to store |
| // a value of the given type; it is analogous to unsafe.Sizeof. |
| Size() uintptr |
| |
| // Bits returns the size of the type in bits. |
| // It is intended for use with numeric types and may overflow |
| // when used for composite types. |
| Bits() int |
| |
| // Align returns the alignment of a value of this type |
| // when allocated in memory. |
| Align() int |
| |
| // FieldAlign returns the alignment of a value of this type |
| // when used as a field in a struct. |
| FieldAlign() int |
| |
| // Kind returns the specific kind of this type. |
| Kind() Kind |
| |
| // Method returns the i'th method in the type's method set. |
| // |
| // For a non-interface type T or *T, the returned Method's Type and Func |
| // fields describe a function whose first argument is the receiver. |
| // |
| // For an interface type, the returned Method's Type field gives the |
| // method signature, without a receiver, and the Func field is nil. |
| Method(int) Method |
| |
| // NumMethods returns the number of methods in the type's method set. |
| NumMethod() int |
| |
| common() *commonType |
| uncommon() *uncommonType |
| } |
| |
| // A Kind represents the specific kind of type that a Type represents. |
| // For numeric types, the Kind gives more information than the Type's |
| // dynamic type. For example, the Type of a float32 is FloatType, but |
| // the Kind is Float32. |
| // |
| // The zero Kind is not a valid kind. |
| type Kind uint8 |
| |
| const ( |
| Bool Kind = 1 + iota |
| Int |
| Int8 |
| Int16 |
| Int32 |
| Int64 |
| Uint |
| Uint8 |
| Uint16 |
| Uint32 |
| Uint64 |
| Uintptr |
| Float32 |
| Float64 |
| Complex64 |
| Complex128 |
| Array |
| Chan |
| Func |
| Interface |
| Map |
| Ptr |
| Slice |
| String |
| Struct |
| UnsafePointer |
| ) |
| |
| // High bit says whether type has |
| // embedded pointers,to help garbage collector. |
| const kindMask = 0x7f |
| |
| func (k Kind) String() string { |
| if int(k) < len(kindNames) { |
| return kindNames[k] |
| } |
| return "kind" + strconv.Itoa(int(k)) |
| } |
| |
| var kindNames = []string{ |
| Bool: "bool", |
| Int: "int", |
| Int8: "int8", |
| Int16: "int16", |
| Int32: "int32", |
| Int64: "int64", |
| Uint: "uint", |
| Uint8: "uint8", |
| Uint16: "uint16", |
| Uint32: "uint32", |
| Uint64: "uint64", |
| Uintptr: "uintptr", |
| Float32: "float32", |
| Float64: "float64", |
| Complex64: "complex64", |
| Complex128: "complex128", |
| Array: "array", |
| Chan: "chan", |
| Func: "func", |
| Interface: "interface", |
| Map: "map", |
| Ptr: "ptr", |
| Slice: "slice", |
| String: "string", |
| Struct: "struct", |
| UnsafePointer: "unsafe.Pointer", |
| } |
| |
| func (t *uncommonType) uncommon() *uncommonType { |
| return t |
| } |
| |
| func (t *uncommonType) PkgPath() string { |
| if t == nil || t.pkgPath == nil { |
| return "" |
| } |
| return *t.pkgPath |
| } |
| |
| func (t *uncommonType) Name() string { |
| if t == nil || t.name == nil { |
| return "" |
| } |
| return *t.name |
| } |
| |
| func (t *commonType) String() string { return *t.string } |
| |
| func (t *commonType) Size() uintptr { return t.size } |
| |
| func (t *commonType) Bits() int { return int(t.size * 8) } |
| |
| func (t *commonType) Align() int { return int(t.align) } |
| |
| func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } |
| |
| func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) } |
| |
| func (t *commonType) common() *commonType { return t } |
| |
| func (t *uncommonType) Method(i int) (m Method) { |
| if t == nil || i < 0 || i >= len(t.methods) { |
| return |
| } |
| p := &t.methods[i] |
| if p.name != nil { |
| m.Name = *p.name |
| } |
| if p.pkgPath != nil { |
| m.PkgPath = *p.pkgPath |
| } |
| m.Type = toType(*p.typ).(*FuncType) |
| fn := p.tfn |
| m.Func = &FuncValue{value: value{m.Type, addr(&fn), canSet}} |
| return |
| } |
| |
| func (t *uncommonType) NumMethod() int { |
| if t == nil { |
| return 0 |
| } |
| return len(t.methods) |
| } |
| |
| // TODO(rsc): 6g supplies these, but they are not |
| // as efficient as they could be: they have commonType |
| // as the receiver instead of *commonType. |
| func (t *commonType) NumMethod() int { return t.uncommonType.NumMethod() } |
| |
| func (t *commonType) Method(i int) (m Method) { return t.uncommonType.Method(i) } |
| |
| func (t *commonType) PkgPath() string { return t.uncommonType.PkgPath() } |
| |
| func (t *commonType) Name() string { return t.uncommonType.Name() } |
| |
| // Len returns the number of elements in the array. |
| func (t *ArrayType) Len() int { return int(t.len) } |
| |
| // Elem returns the type of the array's elements. |
| func (t *ArrayType) Elem() Type { return toType(*t.elem) } |
| |
| // arrayOrSliceType is an unexported method that guarantees only |
| // arrays and slices implement ArrayOrSliceType. |
| func (*ArrayType) arrayOrSliceType() {} |
| |
| // Dir returns the channel direction. |
| func (t *ChanType) Dir() ChanDir { return ChanDir(t.dir) } |
| |
| // Elem returns the channel's element type. |
| func (t *ChanType) Elem() Type { return toType(*t.elem) } |
| |
| func (d ChanDir) String() string { |
| switch d { |
| case SendDir: |
| return "chan<-" |
| case RecvDir: |
| return "<-chan" |
| case BothDir: |
| return "chan" |
| } |
| return "ChanDir" + strconv.Itoa(int(d)) |
| } |
| |
| // In returns the type of the i'th function input parameter. |
| func (t *FuncType) In(i int) Type { |
| if i < 0 || i >= len(t.in) { |
| return nil |
| } |
| return toType(*t.in[i]) |
| } |
| |
| // DotDotDot returns true if the final function input parameter |
| // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the |
| // parameter's underlying static type []T. |
| // |
| // For concreteness, if t is func(x int, y ... float), then |
| // |
| // t.NumIn() == 2 |
| // t.In(0) is the reflect.Type for "int" |
| // t.In(1) is the reflect.Type for "[]float" |
| // t.DotDotDot() == true |
| // |
| func (t *FuncType) DotDotDot() bool { return t.dotdotdot } |
| |
| // NumIn returns the number of input parameters. |
| func (t *FuncType) NumIn() int { return len(t.in) } |
| |
| // Out returns the type of the i'th function output parameter. |
| func (t *FuncType) Out(i int) Type { |
| if i < 0 || i >= len(t.out) { |
| return nil |
| } |
| return toType(*t.out[i]) |
| } |
| |
| // NumOut returns the number of function output parameters. |
| func (t *FuncType) NumOut() int { return len(t.out) } |
| |
| // Method returns the i'th method in the type's method set. |
| func (t *InterfaceType) Method(i int) (m Method) { |
| if i < 0 || i >= len(t.methods) { |
| return |
| } |
| p := &t.methods[i] |
| m.Name = *p.name |
| if p.pkgPath != nil { |
| m.PkgPath = *p.pkgPath |
| } |
| m.Type = toType(*p.typ).(*FuncType) |
| return |
| } |
| |
| // NumMethod returns the number of interface methods in the type's method set. |
| func (t *InterfaceType) NumMethod() int { return len(t.methods) } |
| |
| // Key returns the map key type. |
| func (t *MapType) Key() Type { return toType(*t.key) } |
| |
| // Elem returns the map element type. |
| func (t *MapType) Elem() Type { return toType(*t.elem) } |
| |
| // Elem returns the pointer element type. |
| func (t *PtrType) Elem() Type { return toType(*t.elem) } |
| |
| // Elem returns the type of the slice's elements. |
| func (t *SliceType) Elem() Type { return toType(*t.elem) } |
| |
| type StructField struct { |
| PkgPath string // empty for uppercase Name |
| Name string |
| Type Type |
| Tag string |
| Offset uintptr |
| Index []int |
| Anonymous bool |
| } |
| |
| // Field returns the i'th struct field. |
| func (t *StructType) Field(i int) (f StructField) { |
| if i < 0 || i >= len(t.fields) { |
| return |
| } |
| p := t.fields[i] |
| f.Type = toType(*p.typ) |
| if p.name != nil { |
| f.Name = *p.name |
| } else { |
| t := f.Type |
| if pt, ok := t.(*PtrType); ok { |
| t = pt.Elem() |
| } |
| f.Name = t.Name() |
| f.Anonymous = true |
| } |
| if p.pkgPath != nil { |
| f.PkgPath = *p.pkgPath |
| } |
| if p.tag != nil { |
| f.Tag = *p.tag |
| } |
| f.Offset = p.offset |
| f.Index = []int{i} |
| return |
| } |
| |
| // TODO(gri): Should there be an error/bool indicator if the index |
| // is wrong for FieldByIndex? |
| |
| // FieldByIndex returns the nested field corresponding to index. |
| func (t *StructType) FieldByIndex(index []int) (f StructField) { |
| for i, x := range index { |
| if i > 0 { |
| ft := f.Type |
| if pt, ok := ft.(*PtrType); ok { |
| ft = pt.Elem() |
| } |
| if st, ok := ft.(*StructType); ok { |
| t = st |
| } else { |
| var f0 StructField |
| f = f0 |
| return |
| } |
| } |
| f = t.Field(x) |
| } |
| return |
| } |
| |
| const inf = 1 << 30 // infinity - no struct has that many nesting levels |
| |
| func (t *StructType) fieldByNameFunc(match func(string) bool, mark map[*StructType]bool, depth int) (ff StructField, fd int) { |
| fd = inf // field depth |
| |
| if mark[t] { |
| // Struct already seen. |
| return |
| } |
| mark[t] = true |
| |
| var fi int // field index |
| n := 0 // number of matching fields at depth fd |
| L: |
| for i := range t.fields { |
| f := t.Field(i) |
| d := inf |
| switch { |
| case match(f.Name): |
| // Matching top-level field. |
| d = depth |
| case f.Anonymous: |
| ft := f.Type |
| if pt, ok := ft.(*PtrType); ok { |
| ft = pt.Elem() |
| } |
| switch { |
| case match(ft.Name()): |
| // Matching anonymous top-level field. |
| d = depth |
| case fd > depth: |
| // No top-level field yet; look inside nested structs. |
| if st, ok := ft.(*StructType); ok { |
| f, d = st.fieldByNameFunc(match, mark, depth+1) |
| } |
| } |
| } |
| |
| switch { |
| case d < fd: |
| // Found field at shallower depth. |
| ff, fi, fd = f, i, d |
| n = 1 |
| case d == fd: |
| // More than one matching field at the same depth (or d, fd == inf). |
| // Same as no field found at this depth. |
| n++ |
| if d == depth { |
| // Impossible to find a field at lower depth. |
| break L |
| } |
| } |
| } |
| |
| if n == 1 { |
| // Found matching field. |
| if len(ff.Index) <= depth { |
| ff.Index = make([]int, depth+1) |
| } |
| ff.Index[depth] = fi |
| } else { |
| // None or more than one matching field found. |
| fd = inf |
| } |
| |
| mark[t] = false, false |
| return |
| } |
| |
| // FieldByName returns the struct field with the given name |
| // and a boolean to indicate if the field was found. |
| func (t *StructType) FieldByName(name string) (f StructField, present bool) { |
| return t.FieldByNameFunc(func(s string) bool { return s == name }) |
| } |
| |
| // FieldByNameFunc returns the struct field with a name that satisfies the |
| // match function and a boolean to indicate if the field was found. |
| func (t *StructType) FieldByNameFunc(match func(string) bool) (f StructField, present bool) { |
| if ff, fd := t.fieldByNameFunc(match, make(map[*StructType]bool), 0); fd < inf { |
| ff.Index = ff.Index[0 : fd+1] |
| f, present = ff, true |
| } |
| return |
| } |
| |
| // NumField returns the number of struct fields. |
| func (t *StructType) NumField() int { return len(t.fields) } |
| |
| // Convert runtime type to reflect type. |
| // Same memory layouts, different method sets. |
| func toType(i interface{}) Type { |
| switch v := i.(type) { |
| case nil: |
| return nil |
| case *runtime.BoolType: |
| return (*BoolType)(unsafe.Pointer(v)) |
| case *runtime.FloatType: |
| return (*FloatType)(unsafe.Pointer(v)) |
| case *runtime.ComplexType: |
| return (*ComplexType)(unsafe.Pointer(v)) |
| case *runtime.IntType: |
| return (*IntType)(unsafe.Pointer(v)) |
| case *runtime.StringType: |
| return (*StringType)(unsafe.Pointer(v)) |
| case *runtime.UintType: |
| return (*UintType)(unsafe.Pointer(v)) |
| case *runtime.UnsafePointerType: |
| return (*UnsafePointerType)(unsafe.Pointer(v)) |
| case *runtime.ArrayType: |
| return (*ArrayType)(unsafe.Pointer(v)) |
| case *runtime.ChanType: |
| return (*ChanType)(unsafe.Pointer(v)) |
| case *runtime.FuncType: |
| return (*FuncType)(unsafe.Pointer(v)) |
| case *runtime.InterfaceType: |
| return (*InterfaceType)(unsafe.Pointer(v)) |
| case *runtime.MapType: |
| return (*MapType)(unsafe.Pointer(v)) |
| case *runtime.PtrType: |
| return (*PtrType)(unsafe.Pointer(v)) |
| case *runtime.SliceType: |
| return (*SliceType)(unsafe.Pointer(v)) |
| case *runtime.StructType: |
| return (*StructType)(unsafe.Pointer(v)) |
| } |
| println(i) |
| panic("toType") |
| } |
| |
| // ArrayOrSliceType is the common interface implemented |
| // by both ArrayType and SliceType. |
| type ArrayOrSliceType interface { |
| Type |
| Elem() Type |
| arrayOrSliceType() // Guarantees only Array and Slice implement this interface. |
| } |
| |
| // Typeof returns the reflection Type of the value in the interface{}. |
| func Typeof(i interface{}) Type { return toType(unsafe.Typeof(i)) } |
| |
| // ptrMap is the cache for PtrTo. |
| var ptrMap struct { |
| sync.RWMutex |
| m map[Type]*PtrType |
| } |
| |
| // runtimePtrType is the runtime layout for a *PtrType. |
| // The memory immediately before the *PtrType is always |
| // the canonical runtime.Type to be used for a *runtime.Type |
| // describing this PtrType. |
| type runtimePtrType struct { |
| runtime.Type |
| runtime.PtrType |
| } |
| |
| // PtrTo returns the pointer type with element t. |
| // For example, if t represents type Foo, PtrTo(t) represents *Foo. |
| func PtrTo(t Type) *PtrType { |
| // If t records its pointer-to type, use it. |
| ct := t.common() |
| if p := ct.ptrToThis; p != nil { |
| return toType(*p).(*PtrType) |
| } |
| |
| // Otherwise, synthesize one. |
| // This only happens for pointers with no methods. |
| // We keep the mapping in a map on the side, because |
| // this operation is rare and a separate map lets us keep |
| // the type structures in read-only memory. |
| ptrMap.RLock() |
| if m := ptrMap.m; m != nil { |
| if p := m[t]; p != nil { |
| ptrMap.RUnlock() |
| return p |
| } |
| } |
| ptrMap.RUnlock() |
| ptrMap.Lock() |
| if ptrMap.m == nil { |
| ptrMap.m = make(map[Type]*PtrType) |
| } |
| p := ptrMap.m[t] |
| if p != nil { |
| // some other goroutine won the race and created it |
| ptrMap.Unlock() |
| return p |
| } |
| |
| // runtime.Type value is always right before type structure. |
| // 2*ptrSize is size of interface header |
| rt := (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - uintptr(unsafe.Sizeof(runtime.Type(nil))))) |
| |
| rp := new(runtimePtrType) |
| rp.Type = &rp.PtrType |
| |
| // initialize rp.PtrType using *byte's PtrType as a prototype. |
| // have to do assignment as PtrType, not runtime.PtrType, |
| // in order to write to unexported fields. |
| p = (*PtrType)(unsafe.Pointer(&rp.PtrType)) |
| bp := (*PtrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType))) |
| *p = *bp |
| |
| s := "*" + *ct.string |
| p.string = &s |
| |
| // For the type structures linked into the binary, the |
| // compiler provides a good hash of the string. |
| // Create a good hash for the new string by using |
| // the FNV-1 hash's mixing function to combine the |
| // old hash and the new "*". |
| p.hash = ct.hash*16777619 ^ '*' |
| |
| p.uncommonType = nil |
| p.ptrToThis = nil |
| p.elem = rt |
| |
| ptrMap.m[t] = (*PtrType)(unsafe.Pointer(&rp.PtrType)) |
| ptrMap.Unlock() |
| return p |
| } |