前言

反射是什么? 我们平常也是经常用到, 而且这名词都用烂了, 这里就不再详细介绍了.

简单说, 就是有一个不知道是什么类型的变量, 通过反射可以获取其类型, 并可操作属性和方法.

​ToString​​ToStringInt​​ToStringBool​​ToString​
​PHP​​$a​​$b​​$a->$b()​​Golang​​Golang​

希望看完反射的用法之后, 至少以后再看相关代码不至于一脸懵逼. 甚至于需要的时候还能自己手撸一套.

使用
​Golang​​reflect​
​reflect.Type​​reflect.Value​

官方文档地址: ​​reflect.Type​​ ​​reflect.Value​​

我们在反射中的使用, 也是基于这两个对象的.

对于反射的使用来说, 其实我们在平常使用中, 主要也就用到下面这几种操作, 大部分复杂的操作百年难得一用:

  • 变量类型和属性的操作
  • 变量方法的操作

下面就基于这两种操作进行简单演示.

变量类型和属性的操作

获取属性信息

​reflect.Type​

获取类型


​u​​u := &User{}​​reflect.TypeOf(u).Elem()​
​Array​​Chan​​Map​​Ptr​​Slice​
​Kind​​Kind​

结构体


数组

​Slice​

说白了, 数组其实就是一个指向首地址的指针嘛. 故要想获取数组元素的内容, 做一次取值操作就可以啦.


如果数组中存放的是结构体, 在用作结构体处理就好啦

map


获取属性值

​reflect.Value​​reflect.ValueOf​
​Value​​Interface​​Interface{}​

基础类型

​GO​


结构体

如果是自定义的结构体怎么取值呢? 这, 一直找到基础类型. 因为所有的自定义结构体都是有基础类型组成的嘛.


数组

如果是数组呢? 也很简单


map

​Map​​Value​​Value​​Map​​key​​value​


属性赋值

​reflect.Value​​Set​

这里注意, 只有指针类型的的变量才能被赋值. 其实很好理解, 值类型在方法调用时是通过复制传值的. 只有传递指针才能够找到原始值的内存地址进行修改.

​Kind​​Value​

以下所有的赋值操作, 都可以与取值操作联动进行.

基础类型


结构体

​Value​

需要注意的一点, 结构体只有公共字段才能够通过反射进行赋值, 若赋值给一个私有字段, 会抛出异常.


数组

​Set​
​func (v Value) Set(x Value)​
​Set​​Value​​Set​


map


创建空值 Value

​New​​Value​​Value​

此操作的好处是, 在使用过程中, 完全不需要判断对象类型.


变量方法的操作

普通方法

普通方法指未依附与结构体的方法.


结构体方法

获取方法信息

这里需要注意, 结构体指针和对象所拥有的方法数量是不同的, 具体可看: ​​https://hujingnb.com/archives/348​​


方法调用