学过后端的同学应该很清楚反射的意思。当我们使用一个类的时候必定知道它什么在对该类进行实例化,最后使用new出来的新对象进行操作
Buy buy = new Buy(); buy.getApple(99);
反射指的是跟正常的类加载机制相反。我们初始情况下不清楚需要加载什么,需要在类加载的过程中去配置指定的类,Go语言中提供有这样的机制,在运行中更新变量并进行检查他们的值与方法且进行使用,但是在编译代码时并不清除这些变量的类型,这就是反射机制。
在 reflect 包中定义了各种类型,实现了反射的各种函数,通过它们可以在运行时检测类型的信息、改变类型的值。
Class name = Class.forName("com.test.reflect.Buy"); Method method = name.getMethod("getApple", int.class); Constructor constructor = name.getConstructor(); Object object = constructor.newInstance(); method.invoke(object, 4);
在 Go 中声明变量会有两种类型,分别为静态和动态数据类型
//静态数据类型 var age int var name string //动态数据类型 var type interface{} type =99 type = "hellow Go"
type声明的初始类型是interface类型所以type的静态类型就是interface类型。在运行到后面的时候type被修改为int类型,最后被改为了string类型,动态类型是指系统运行时才能看到的类型。
每个对象声明后都会拥有一个不变的静态类型,无论它的动态类型是什么,interface中的底层数据结构保存了两个指针分别是类型和数据,类型指针中保存有静态和动态类型,因为有动态类型的存在,包含了接口类型参数的函数中是无法提前知道传递进来的类型变量的,这里就需要使用到了反射进行处理不同的类型。在Java中是通过Class机制来加载已存在类的路径,在Go中不存在类的概念只有基本数据类型,结构体在基础数据类型创建出来的,所以可以使用interface可以兼容这一切作用于反射,也因此反射的操作被分为类型(type)与值(value)
接口值在反射机制中可以理解为由reflect.Type和reflect.Value这俩个进行组成
- type(类型)用于定位需要反射对象的类型
- value(值) 用来定位对象的值并进行操作
reflect.TypeOf() 函数可以获取到任意值的类型对象,通过类型对象获取类型信息,在通过相关的API方法来区分当前对象的数据类型。
reflect.ValueOf()函数用于操作值。
通过反射机制修改值并不是所有值都可以修改的,需要满足以下俩个条件
- 被修改的是数据对应的指针地址而非指针地址的value
- 不是结构体的中非公开字体
反射修改变量的值中需要注意函数参数传递的是拷贝的值,必须传递变量地址才能修改到变量值。
本文正在参加技术专题18期-聊聊Go语言框架