反射 reflection 特性描述
- 反射可大大提供程序的灵活性、使得interface{}有更大的发挥余地
- 反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息
- 发射会将匿名字段作为独立字段 (匿名字段本质)
- 利用反射修改对象状态、前提是 interface.data 是 settable,即 pointer-interface
- 通过发射可以 “动态”调用方法
reflect 包涉及到源码文件
$GOPATH/src/reflect/value.go && type.go 文件,下面例子中调用API函数如下。
// Two Type values are equal if they represent identical types.
type Type interface {
// Methods applicable to all types.
// lexicographic order.
Method(int) Method
// For an interface type, the returned Method's Type field gives the
// method signature, without a receiver, and the Func field is nil.
MethodByName(string) (Method, bool)
// NumMethod returns the number of exported methods in the type's method set.
NumMethod() int
// NumMethod returns the number of exported methods in the type's method set.
NumMethod() int
// Name returns the type's name within its package for a defined type.
// For other (non-defined) types it returns the empty string.
Name() string
// PkgPath returns a defined type's package path, that is, the import path
// that uniquely identifies the package, such as "encoding/base64".
// If the type was predeclared (string, error) or not defined (*T, struct{},
// []int, or A where A is an alias for a non-defined type), the package path
// will be the empty string.
PkgPath() string
// Kind returns the specific kind of this type.
Kind() Kind
// IsVariadic panics if the type's Kind is not Func.
IsVariadic() bool
// Elem returns a type's element type.
// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
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
// FieldByIndex returns the nested field corresponding
// to the index sequence. It is equivalent to calling Field
// successively for each index i.
// It panics if the type's Kind is not Struct.
FieldByIndex(index []int) StructField
// FieldByName returns the struct field with the given name
// and a boolean indicating if the field was found.
FieldByName(name string) (StructField, bool)
// NumField returns a struct type's field count.
// It panics if the type's Kind is not Struct.
NumField() int
// NumIn returns a function type's input parameter count.
// It panics if the type's Kind is not Func.
NumIn() int
// NumOut returns a function type's output parameter count.
// It panics if the type's Kind is not Func.
NumOut() int
// Out returns the type of a function type's i'th output parameter.
// It panics if the type's Kind is not Func.
// It panics if i is not in the range [0, NumOut()).
Out(i int) Type
common() *rtype
uncommon() *uncommonType
}
响应的方法源码,请读者自行查看源码。
实例1
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (user User) hello() {
fmt.Println("hello world")
}
func main() {
u := User{2, "zhangsan", 22}
Info(u)
}
func Info(o interface{}) {
t := reflect.TypeOf(o)
fmt.Println("Type: ", t.Name())
if K := t.Kind(); K != reflect.Struct{
fmt.Println("传入的类型不对,需用传对象或者基本数据类型的地址值")
return
}
v := reflect.ValueOf(o)
fmt.Println("field: ")
for i :=0; i < t.NumField(); i++ {
f := t.Field(i)
val := v.Field(i).Interface()
fmt.Printf("%6s: %v = %v \n",f.Name, f.Type, val)
}
for i :=0; i < t.NumMethod(); i++ {
m := t.Method(i)
fmt.Printf("%6s: %v \n", m.Name, m.Type)
}
}
运行结果
~/gomod/reflect$ go run reflect.go
Type: User
field:
Id: int = 2
Name: string = zhangsan
Age: int = 22
实例2
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (u User) Hello(name string){
fmt.Println("hello method:", name,",say my name is",u.Name)
}
func main() {
u := User{1,"hale",22}
v := reflect.ValueOf(u)
//get object hello method
mv := v.MethodByName("Hello")
// make slice
args := []reflect.Value{reflect.ValueOf("jay")}
//
mv.Call(args)
}
运行结果
/gomod/src/reflect$ go run reflect1.go
hello method: jay ,say my name is hale