反射来自元编程,指通过类型检查变量本身数据结构的方式,只有部分编程语言支持反射。

Go 语言提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制。

在什么情况下需要反射

  1. 不能明确接口调用哪个函数,需要根据传入的参数在运行时决定。
  2. 不能明确传入函数的参数类型,需要在运行时处理任意对象。

类型

反射构建在类型系统之上,Go是静态类型语言,每一个变量都有静态类型,在编译时就确定下来了。

比如

  1. type MyInt int
  2. var i int
  3. var j MyInt

i和j的底层类型都是int,但i的静态类型是int,j的静态类型是MyInt,这两个是不同类型,是不能直接赋值的,需要类型强制转换。

掌握reflect包的以下函数:

  1. reflect.ValueOf({}interface) reflect.Value:获取某个变量的值,但值是通过reflect.Value对象描述的。
  2. reflect.TypeOf({}interface) reflect.Type:获取某个变量的静态类型,但值是通过reflect.Type对象描述的,是可以直接使用Println打印的。
  3. reflect.Value.Kind() Kind:获取变量值的底层类型(类别),注意不是类型,是Int、Float,还是Struct,还是Slice,具体见此
  4. reflect.Value.Type() reflect.Type:获取变量值的类型,效果等同于reflect.TypeOf。

再解释下Kind和Type的区别

  1. type MyInt int
  2. var x MyInt = 7
  3. v := reflect.ValueOf(x)

v.Kind()得到的是Int,而Type得到是MyInt。

反射原理

反射的意思是在运行时,能够动态知道给定数据对象的类型和结构,并有机会修改它!
现在一个数据对象,如何判断它是什么结构?
数据interface中保存有结构数据呀,只要想办法拿到该数据对应的内存地址,然后把该数据转成interface,通过查看interface中的类型结构,就可以知道该数据的结构了呀~

如何实现字符串和byte切片的零拷贝

  1. func string2bytes(s string) []byte {
  2. return *(*[]byte)(unsafe.Pointer(&s))
  3. }
  4. func bytes2string(b []byte) string{
  5. return *(*string)(unsafe.Pointer(&b))
  6. }

原理上是利用指针的强转