美文网首页
go reflection

go reflection

作者: xikaka | 来源:发表于2018-07-02 17:24 被阅读0次

    1. 接口描述

    一个接口变量类型里面存储一个键值对: 赋给接口变量的具体值,该值对应的类型描述。
    举个例子:

    var r io.Reader
    tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
    if err != nil {
        return nil, err
    }
    r = tty
    

    r 包含的键值对(value, type)为(tty, *os.File), 其中类型*os.File不仅包含Read方法,还包含所有它自己实现的方法。tty包含值本身和类型相关的所有信息。

    2. 反射

    a. reflect.Value类型包含有Type方法,可以获取它的type类型。
    b. reflect.Value和relfect.Type都有Kind方法,返回存储的具体底部类型。
    c. 可以通过调用set方法,设置反射后实例的值,但是被反射的实例必须是引用类型,因为按值拷贝的变量反射后改变的是本身的值, 而这样操作并没有任何意义。为避免这种无意义的操作,调用这种操作会导致程序panic。
    对于c的补充示例

    var x float64 = 3.4
    v := reflect.ValueOf(x)
    v.SetFloat(7.1) // Error: will panic.
    
    panic: reflect.Value.SetFloat using unaddressable value
    

    反射实例v 不能被赋值, 可以通过以下方法进行判断

    var x float64 = 3.4
    v := reflect.ValueOf(x)
    fmt.Println("settability of v:", v.CanSet())
    //settability of v: false
    

    反射对象是否能进行改值操作,取决于反射对象是否持有原有的对象,而不是原有对象的一份拷贝。如下:

    var x float64 = 3.4
    p := reflect.ValueOf(&x) // Note: take the address of x.
    fmt.Println("type of p:", p.Type())
    fmt.Println("settability of p:", p.CanSet())
    

    对于struct类型的操作

    type T struct {
        A int
        B string
    }
    t := T{23, "skidoo"}
    s := reflect.ValueOf(&t).Elem()
    typeOfT := s.Type()
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        fmt.Printf("%d: %s %s = %v\n", i,
            typeOfT.Field(i).Name, f.Type(), f.Interface()) //注意此处通过reflect.Type来获取字段的名字。
    }
    

    由于s中持有的是类型的引用,我们可以直接对s的字段进行赋值

    s.Field(0).SetInt(77)
    s.Field(1).SetString("Sunset Strip")
    fmt.Println("t is now", t)
    

    d. 可以通过调用reflect.Value的interface方法进行拆包操作,获取反射对应的实例(interface类型)

    相关文章

      网友评论

          本文标题:go reflection

          本文链接:https://www.haomeiwen.com/subject/uqpluftx.html