反射是指能够自描述和自控制,通过采用某种机制来实现对自己行为的描述。Golang语言实现了反射,反射机制就是在运行时动态的调用对象的方法和属性,官方自带的reflect包就是反射相关的
Golang设计的原则中变量包括(type, value)两部分,反射主要与Golang的interface类型相关,只有interface类型才有反射机制,实现路径为src/reflect文件中
静态类型语言。每个变量的类型在编译时都是确定的:int,float32, *AutoType, []byte,
动态类型:运行时给这个变量复制(如果值为nil的时候没有动态类型)。一个变量的动态类型在运行时可能改变,这主要依赖于它的赋值(前提是这个变量时接口类型)
type Type interface {
// Methods applicable to all types.
// Align returns the alignment in bytes of a value of
// this type when allocated in memory.
Align() int
// FieldAlign returns the alignment in bytes of a value of
// this type when used as a field in a struct.
FieldAlign() int
Name() string
Kind() Kind
Elem() Type
// Field returns a struct type's i'th field.
// It panics if the type's Kind is not Struct.
// It panics if i is not in the range [0, NumField()).
Field(i int) StructField
// Key returns a map type's key type.
// It panics if the type's Kind is not Map.
Key() Type
// Len returns an array type's length.
// It panics if the type's Kind is not Array.
Len() int
const (
Invalid Kind = iota
Bool
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
)
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ *rtype
word unsafe.Pointer
}
动态获取输入参数接口中的值的类型,如果接口为空则返回nil
转换为emptyInterface
// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i interface{}) Type {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
}
size:
存储这个类型的一个值所需要的字节数(值占用的字节数)algin:
这个类型的一个变量在内存中的对齐后的所用的字节数 (变量占的字节数)FieldAlign
: 这种类型的变量如果是struct中的字段,那么它对齐后所用的字节数// rtype is the common implementation of most values.
// It is embedded in other struct types.
//
// rtype must be kept in sync with ../runtime/type.go:/^type._type.
type rtype struct {
size uintptr
ptrdata uintptr // number of bytes in the type that can contain pointers
hash uint32 // hash of type; avoids computation in hash tables
tflag tflag // extra type information flags
align uint8 // alignment of variable with this type
fieldAlign uint8 // alignment of struct field with this type
kind uint8 // enumeration for C
alg *typeAlg // algorithm table
gcdata *byte // garbage collection data
str nameOff // string form
ptrToThis typeOff // type for pointer to this type, may be zero
}
Value描述对象的值信息,并不是所有的方法对任何的类型都有意义,特定的方法只适用于特定的类型
type Value struct {
// typ holds the type of the value represented by a Value.
typ *rtype
// Pointer-valued data or, if flagIndir is set, pointer to data.
// Valid when either flagIndir is set or typ.pointers() is true.
ptr unsafe.Pointer
// flag holds metadata about the value.
// The lowest bits are flag bits:
// - flagStickyRO: obtained via unexported not embedded field, so read-only
// - flagEmbedRO: obtained via unexported embedded field, so read-only
// - flagIndir: val holds a pointer to the data
// - flagAddr: v.CanAddr is true (implies flagIndir)
// - flagMethod: v is a method value.
// The next five bits give the Kind of the value.
// This repeats typ.Kind() except for method values.
// The remaining 23+ bits give a method number for method values.
// If flag.kind() != Func, code can assume that flagMethod is unset.
// If ifaceIndir(typ), code can assume that flagIndir is set.
flag
// A method value represents a curried method invocation
// like r.Read for some receiver r. The typ+val+flag bits describe
// the receiver r, but the flag's Kind bits say Func (methods are
// functions), and the top bits of the flag give the method number
// in r's type's method table.
}
Golang reflect慢主要有两个原因
package main
import (
"fmt"
"reflect"
)
type Bird struct {
name string
age int
location string
}
func (b Bird) Sing() string {
return "sing func"
}
func (b *Bird) Fly() string {
return "fly func"
}
func (b *Bird) Eat() {
}
func main() {
bird := Bird{
name: "pig",
age: 100,
location: "Beijing",
}
t := reflect.TypeOf(bird)
fmt.Printf("type t = %#v\n", t)
fmt.Printf("type name = %#v\n", t.Name())
fmt.Printf("type string = %#v\n", t.String())
fmt.Printf("type pkg path = %#v\n", t.PkgPath())
fmt.Printf("type kind = %#v\n", t.Kind())
fmt.Printf("type size = %#v\n", t.Size())
fieldType, _ := t.FieldByName("age")
fmt.Printf("type field: %v", fieldType)
v := reflect.ValueOf(bird)
fmt.Printf("value of: %#v\n", v)
fmt.Printf("value of Type: %#v\n", v.Type())
fmt.Printf("value of Type name: %#v\n", v.Type().Name())
fmt.Printf("value of Type size: %#v\n", v.Type().Size())
fmt.Printf("value of Type kind: %#v\n", v.Type().Kind())
fieldValue := v.FieldByName("age")
fmt.Printf("value field age = %#v", fieldValue)
}