GO-反射

作者: RedHatMe | 来源:发表于2019-10-11 21:19 被阅读0次

    接口的特色

    var r io.Reader
    tty, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)
    if err != nil { return nil, err }
    r = tty
    var w io.Writer
    w = r.(io.Writer)
    
    
    1. tty 是*os.File 类型。此类型实现了io.Reader中的Read()和io.Writer()中的Write()方法 以及一些其他的方法。所以可以进行赋值。
    2. 接口类型的变量存储了两个内容:赋值给变量实际的值和这个值的类型描述。即(value,type)对。更准确的说,值是底层实现了接口的实际数据项目,而类型描述了这个项目完整的类型。

    反射三原则-1-从接口值到反射对象的反射。

    reflect.TypeOf 反射出对象的类型
    reflect.ValueOf 反射出对象的值

    type MyInt int
    var x MyInt = 7
    v := reflect.ValueOf(x)
    
    v.Kind() = reflect.Int  != reflect.MyInt  
    
    1. 反射对象的 Kind 描述了底层类型,而不是静态类型。如果一个反射对象包含了用户定义的整数类型的值 。
    2. v 的 Kind 仍然是 reflect.Int,尽管 x 的静态类型是 MyInt,而不是 int。换句话说,Kind 无法从 MyInt 中区分 int,而 Type 可以。

    反射三原则-2-从反射对象到接口值的反射。

    从 reflect.Value 可以使用 Interface() 方法还原接口值。
    简单来说,Interface 方法是 ValueOf 函数的镜像。
    其实我不明白为啥要这个东西。

    反射三原则-3-为了修改反射对象,其值必须可设置。

    也就是在Set值之前调用CanSet()去判断。
    可以肯定的是,我们在修改反射对象之前,必须传它的指针,
    因为传值没有意义,会发生复制。也就是再怎么set 也不是原来的对象了。如下:

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

    虽然 v 看起来是从 x 创建的,它也无法更新 x。反之,如果在反射值内部允许更新 x 的副本,那么 x 本身不会收到影响。这会造成混淆,并且毫无意义,因此这是非法的,而设置性是用于解决这个问题的属性。

    这很神奇?其实不是。这实际上是一个常见的非同寻常的情况。 就是值传递和指针传递。

    下面就不会错。

    var x float64 = 3.4
    p := reflect.ValueOf(&x) // 注意:获取 X 的地址。
    fmt.Println("type of p:", p.Type())
    v := p.Elem()
    fmt.Println("settability of p:" , v.CanSet())
    

    引用:
    https://mikespook.com/2011/09/%e5%8f%8d%e5%b0%84%e7%9a%84%e8%a7%84%e5%88%99/

    相关文章

      网友评论

          本文标题:GO-反射

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