反射

什么是反射

TypeOfValueOf

相关类型与方法

func TypeOf
func TypeOf(i interface{}) Type
TypeOfTypeOf(nil)

type Type

type Type interface {//Type 是一个接口
	// Kind返回该接口的具体分类
    Kind() Kind
    
    // Name返回该类型在自身包内的类型名,如果是未命名类型会返回""
    Name() string
    
    // 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic
    NumField() int
    
    // 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
    Field(i int) StructField
    
    // 返回该类型的方法集中方法的数目
    // 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法;
    // 匿名字段导致的歧义方法会滤除
    NumMethod() int
    
    // 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic
    // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
    // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
    Method(int) Method
    /*
    还有其他的方法,暂且省略
    */
}

Kind返回该接口的具体分类
Kind() Kind

func ValueOf
func ValueOf(i interface{}) Value
ValueOfValueOf(nil)

type Value

type Value struct {
    // 内含隐藏或非导出字段
}

Value对象有很多方法,如

func (Value)
func (v Value) Type() Type

返回v持有的值的类型的Type表示。

func (Value) Int
func (v Value) Int() int64
int64Int、Int8、Int16、Int32、Int64
func (Value) Float
func (v Value) Float() float64
float64Float32、Float64
func (Value) NumField
func (v Value) NumField() int
Struct
func (Value) Field
func (v Value) Field(i int) Value
Struct
func (Value) NumMethod
func (v Value) NumMethod() int

返回v持有值的方法集的方法数目。

func (Value) Method
func (v Value) Method(i int) Value

返回v持有值类型的第i个方法的已绑定(到v的持有值的)状态的函数形式的Value封装。返回值调用Call方法时不应包含接收者;返回值持有的函数总是使用v的持有者作为接收者(即第一个参数)。如果i出界,或者v的持有值是接口类型的零值(nil),会panic。

func (Value) Interface
func (v Value) Interface() (i interface{})

本方法返回v当前持有的值(表示为/保管在interface{}类型),等价于:

var i interface{} = (v's underlying value)

如果v是通过访问非导出结构体字段获取的,会导致panic。

type Kind

type Kind uint

Kind代表Type类型值表示的具体分类。零值表示非法分类。

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
)
type Method
type Method struct {
    // Name是方法名。PkgPath是非导出字段的包路径,对导出字段该字段为""。
    // 结合PkgPath和Name可以从方法集中指定一个方法。
    // 参见http://golang.org/ref/spec#Uniqueness_of_identifiers
    Name    string
    PkgPath string
    Type  Type  // 方法类型
    Func  Value // 方法的值
    Index int   // 用于Type.Method的索引
}

实例

获取原对象的Type和Value值

    package main

    import (
        "fmt"
        "reflect"
    )

    func main() {
        pi := 3.1415
        t := reflect.TypeOf(pi)  //获取pi的类型信息
        v := reflect.ValueOf(pi) //获取pi的值信息
        if t.Kind() == reflect.Float64 {
            fmt.Println("Type",t,"value", v.Float())//如果v不是float32或者float64会panic
        }
    }
Type float64 value 3.1415

比较type与kind

    package main

    import (
        "fmt"
        "reflect"
    )

    type people struct{
        name string 
        age int
    }
    func main() {
        pi := 3.1415
        p :=people{"kyl",18}
        t := reflect.TypeOf(pi)  
        v := reflect.ValueOf(pi)
        if t.Kind() == reflect.Float64 {
            fmt.Println("Type",t,"value", v.Float(),"kind",v.Kind())
        }
        t=reflect.TypeOf(p)
        v=reflect.ValueOf(p)
        fmt.Println("Type",t,"value",v,"Kind",t.Kind())
    }
Type float64 value 3.1415 kind float64Type main.people value {kyl 18} Kind struct

可见type与kind不完全一样,尤其体现在自定义类型上

获取结构体内容和方法信息

    package main

    import (
        "fmt"
        "reflect"
    )

    type student struct {
        ID    int
        Name  string
        Sex   bool
        Grade float32
    }

    func (s student) Myname() {
        fmt.Println("my name is", s.Name)
    }

    func (s student) Sayhi() {
        fmt.Println("hi nice to meet you!")
    }

    func structinfo(o interface{}) { //可以传入任何结构类型的对象
        t := reflect.TypeOf(o)
        if k := t.Kind(); k != reflect.Struct {
            fmt.Println("not a struct")
            return
        }
        fmt.Println("struct name is", t.Name())
        fmt.Println("fields of struct is:")
        v := reflect.ValueOf(o)
        for i := 0; i < t.NumField(); i++ {
            fmt.Println(t.Field(i).Type, ":", v.Field(i).Interface())
        }
        fmt.Println("Methods of struct is:")
        for i:=0;i<t.NumMethod();i++{
            fmt.Println(t.Method(i).Name,":",t.Method(i).Type,v.Method(i))//只能反射公有的方法
        }
    }
    func main() {
        stu := student{1, "kyl", true, 96.5}
        structinfo(stu)
    }
struct name is student fields of struct is: int : 1 string : kyl bool : true float32 : 96.5 Methods of struct is: Myname : func(main.student) 0x48c4e0 Sayhi : func(main.student) 0x48c4e0