| // 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" | |
| "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. | |
| */ | |
| type commonType struct { | |
| size uintptr | |
| hash uint32 | |
| alg uint8 | |
| align uint8 | |
| fieldAlign uint8 | |
| string *string | |
| *uncommonType | |
| } | |
| 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 | |
| } | |
| // Float32Type represents a float32 type. | |
| type Float32Type struct { | |
| commonType | |
| } | |
| // Float64Type represents a float64 type. | |
| type Float64Type struct { | |
| commonType | |
| } | |
| // FloatType represents a float type. | |
| type FloatType struct { | |
| commonType | |
| } | |
| // Complex64Type represents a complex64 type. | |
| type Complex64Type struct { | |
| commonType | |
| } | |
| // Complex128Type represents a complex128 type. | |
| type Complex128Type struct { | |
| commonType | |
| } | |
| // ComplexType represents a complex type. | |
| type ComplexType struct { | |
| commonType | |
| } | |
| // Int16Type represents an int16 type. | |
| type Int16Type struct { | |
| commonType | |
| } | |
| // Int32Type represents an int32 type. | |
| type Int32Type struct { | |
| commonType | |
| } | |
| // Int64Type represents an int64 type. | |
| type Int64Type struct { | |
| commonType | |
| } | |
| // Int8Type represents an int8 type. | |
| type Int8Type struct { | |
| commonType | |
| } | |
| // IntType represents an int type. | |
| type IntType struct { | |
| commonType | |
| } | |
| // Uint16Type represents a uint16 type. | |
| type Uint16Type struct { | |
| commonType | |
| } | |
| // Uint32Type represents a uint32 type. | |
| type Uint32Type struct { | |
| commonType | |
| } | |
| // Uint64Type represents a uint64 type. | |
| type Uint64Type struct { | |
| commonType | |
| } | |
| // Uint8Type represents a uint8 type. | |
| type Uint8Type struct { | |
| commonType | |
| } | |
| // UintType represents a uint type. | |
| type UintType struct { | |
| commonType | |
| } | |
| // StringType represents a string type. | |
| type StringType struct { | |
| commonType | |
| } | |
| // UintptrType represents a uintptr type. | |
| type UintptrType struct { | |
| commonType | |
| } | |
| // UnsafePointerType represents an unsafe.Pointer type. | |
| type UnsafePointerType struct { | |
| commonType | |
| } | |
| // ArrayType represents a fixed array type. | |
| type ArrayType struct { | |
| commonType | |
| 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 | |
| elem *runtime.Type | |
| dir uintptr | |
| } | |
| // FuncType represents a function type. | |
| type FuncType struct { | |
| commonType | |
| 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 | |
| methods []imethod | |
| } | |
| // MapType represents a map type. | |
| type MapType struct { | |
| commonType | |
| key *runtime.Type | |
| elem *runtime.Type | |
| } | |
| // PtrType represents a pointer type. | |
| type PtrType struct { | |
| commonType | |
| elem *runtime.Type | |
| } | |
| // SliceType represents a slice type. | |
| type SliceType struct { | |
| commonType | |
| elem *runtime.Type | |
| } | |
| // 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 | |
| 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 | |
| // 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 | |
| // For non-interface types, Method returns the i'th method with receiver T. | |
| // For interface types, Method returns the i'th method in the interface. | |
| // NumMethod returns the number of such methods. | |
| Method(int) Method | |
| NumMethod() int | |
| uncommon() *uncommonType | |
| } | |
| 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) Align() int { return int(t.align) } | |
| func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } | |
| 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 = newFuncValue(m.Type, addr(&fn), true) | |
| 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) } | |
| // 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, the parameter's underlying static | |
| // type - either interface{} or []T - is returned by t.In(t.NumIn() - 1). | |
| // | |
| // 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 interface method. | |
| 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. | |
| 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) fieldByName(name string, mark map[*StructType]bool, depth int) (ff StructField, fd int) { | |
| fd = inf // field depth | |
| if _, marked := mark[t]; marked { | |
| // 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 f.Name == name: | |
| // Matching top-level field. | |
| d = depth | |
| case f.Anonymous: | |
| ft := f.Type | |
| if pt, ok := ft.(*PtrType); ok { | |
| ft = pt.Elem() | |
| } | |
| switch { | |
| case ft.Name() == 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.fieldByName(name, 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) { | |
| if ff, fd := t.fieldByName(name, 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.Float32Type: | |
| return (*Float32Type)(unsafe.Pointer(v)) | |
| case *runtime.Float64Type: | |
| return (*Float64Type)(unsafe.Pointer(v)) | |
| case *runtime.ComplexType: | |
| return (*ComplexType)(unsafe.Pointer(v)) | |
| case *runtime.Complex64Type: | |
| return (*Complex64Type)(unsafe.Pointer(v)) | |
| case *runtime.Complex128Type: | |
| return (*Complex128Type)(unsafe.Pointer(v)) | |
| case *runtime.IntType: | |
| return (*IntType)(unsafe.Pointer(v)) | |
| case *runtime.Int8Type: | |
| return (*Int8Type)(unsafe.Pointer(v)) | |
| case *runtime.Int16Type: | |
| return (*Int16Type)(unsafe.Pointer(v)) | |
| case *runtime.Int32Type: | |
| return (*Int32Type)(unsafe.Pointer(v)) | |
| case *runtime.Int64Type: | |
| return (*Int64Type)(unsafe.Pointer(v)) | |
| case *runtime.StringType: | |
| return (*StringType)(unsafe.Pointer(v)) | |
| case *runtime.UintType: | |
| return (*UintType)(unsafe.Pointer(v)) | |
| case *runtime.Uint8Type: | |
| return (*Uint8Type)(unsafe.Pointer(v)) | |
| case *runtime.Uint16Type: | |
| return (*Uint16Type)(unsafe.Pointer(v)) | |
| case *runtime.Uint32Type: | |
| return (*Uint32Type)(unsafe.Pointer(v)) | |
| case *runtime.Uint64Type: | |
| return (*Uint64Type)(unsafe.Pointer(v)) | |
| case *runtime.UintptrType: | |
| return (*UintptrType)(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)) | |
| } | |
| panic("toType") | |
| } | |
| // ArrayOrSliceType is the common interface implemented | |
| // by both ArrayType and SliceType. | |
| type ArrayOrSliceType interface { | |
| Type | |
| Elem() Type | |
| } | |
| // Typeof returns the reflection Type of the value in the interface{}. | |
| func Typeof(i interface{}) Type { return toType(unsafe.Typeof(i)) } |