在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
目录
反射概念
关于静态类型你肯定知道Go是静态类型语言,比如
Q: i 和j 类型相同吗? 特殊的静态类型interfaceinterface类型是一种特殊的类型,它代表方法集合。 它可以存放任何实现了其方法的值。 经常被拿来举例的是io包里的这两个接口类型:
任何类型,比如某struct,只要实现了其中的Read()方法就被认为是实现了Reader接口,只要实现了Write()方法,就被认为是实现了Writer接口,不过方法参数和返回值要跟接口声明的一致。 接口类型的变量可以存储任何实现该接口的值。 特殊的interface类型最特殊的interface类型为空interface类型,即interface {},前面说了,interface用来表示一组方法集合,所有实现该方法集合的类型都被认为是实现了该接口。那么空interface类型的方法集合为空,也就是说所有类型都可以认为是实现了该接口。 个类型实现空interface并不重要,重要的是一个空interface类型变量可以存放所有值,记住是所有值,这才是最最重要的。 这也是有些人认为Go是动态类型的原因,这是个错觉。 interface类型是如何表示的
还是以上面的io.Reader为例进行说明,io.Reader是一个接口类型,os.OpenFile()方法返回一个File结构体类型变量,该结构体类型实现了io.Reader的方法,那么io.Reader类型变量就可以用来接收该返回值。如下所示:
那么问题来了。 Q: r的类型是什么? Q:那File类型体现在哪里? Q:如何将r转换成另一个类型结构体变量?比如转换成io.Writer A:使用类型断言,如w = r.(io.Writer). 意思是如果r所持有的元素如果同样实现了io.Writer接口,那么就把值传递给w。 反射三定律为了引出interface,之所以讲interface是想说interface类型有个(value,type)对,而 反射就是检查interface的这个(value, type)对的。 具体一点说就是Go提供一组方法提取interface的value,提供另一组方法提取interface的type. 官方提供了三条定律来说明反射,比较清晰,下面也按照这三定律来总结。 反射包里有两个接口类型要先了解一下.
下面会提到反射对象,所谓反射对象即反射包里提供的两种类型的对象。
反射第一定律:反射可以将interface类型变量转换成反射对象下面示例,看看是如何通过反射获取一个变量的值和类型的:
程序输出如下:
注意:反射是针对interface类型变量的,其中TypeOf()和ValueOf()接受的参数都是interface{}类型的,也即x值是被转成了interface传入的。 除了reflect.TypeOf()和reflect.ValueOf(),还有其他很多方法可以操作,本文先不过多介绍,否则一不小心会会引起困惑。 反射第二定律:反射可以将反射对象还原成interface对象之所以叫
对象x转换成反射对象v,v又通过Interface()接口转换成interface对象,interface对象通过.(float64)类型断言获取float64类型的值。 反射第三定律:反射对象可修改,value值必须是可设置的通过反射可以将interface类型变量转换成反射对象,可以使用该反射对象设置其持有的值。在介绍何谓反射对象可修改前,先看一下失败的例子:
如下代码,通过反射对象v设置新值,会出现panic。报错如下:
错误原因即是v是不可修改的。 反射对象是否可修改取决于其所存储的值,回想一下函数传参时是传值还是传址就不难理解上例中为何失败了。 上例中,传入 想到此处,即可明白,如果构建v时使用x的地址就可实现修改了,但此时v代表的是指针地址,我们要设置的是指针所指向的内容,也即我们想要修改的是
总结这里只是介绍了反射的一些基本用法, 还有很多方法没有涉及,可以参考优秀的开源项目做进一步的学习
|
请发表评论