golang学习——反射

反射

什么是反射

  • 可以理解为逆映射
  • 正向 类型、值 —>对象/变量
  • 反向 对象/变量 —>类型、值
  • 反射(Reflection)是获取程序运行时类型信息的方式
  • 程序员可以利用这些类型信息进行一些更加灵活的处理,如:
    • 让静态语言具备更加多样的运行时动态特征
    • 让程序具备自省能力,使得interface{}接口对象的灵活性有更大的发挥余地
  • go语言提供了名为reflect的反射包,可以:
    • 获取原对象的Type和Value值
    • 修改原对象的Value值
    • 动态调用原对象的方法
    • ……
  • reflect包实现了运行时反射,允许程序操作任意类型的对象。典型用法是用静态类型interface{}保存一个值,通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。Zero接受一个Type类型参数并返回一个代表该类型零值的Value类型值。

相关类型与方法

func TypeOf

func TypeOf(i interface{}) Type

TypeOf返回接口中保存的值的类型,TypeOf(nil)会返回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

Method

func ValueOf

func ValueOf(i interface{}) Value

ValueOf返回一个初始化为i接口保管的具体值的Value,ValueOf(nil)返回Value零值。

type Value

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

Value对象有很多方法,如

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

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

func (Value) Int
func (v Value) Int() int64

返回v持有的有符号整数(表示为int64),如果v的Kind不是Int、Int8、Int16、Int32、Int64会panic

func (Value) Float
func (v Value) Float() float64

返回v持有的浮点数(表示为float64),如果v的Kind不是Float32、Float64会panic

func (Value) NumField
func (v Value) NumField() int

返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic

func (Value) Field
func (v Value) Field(i int) Value

返回结构体的第i个字段(的Value封装)。如果v的Kind不是Struct或i出界会panic

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 float64
Type 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jinniulema

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值