美文网首页
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