上节我们简单了解了下reflect.Type接口的用处,得知它主要提供关于类型相关的信息

这节来了解一下reflect.Value结构体,它包含了许多方法,以供我们动态获取、修改值,或者调用方法

先从一个例子入手:

将i变量转为具体的int类型,可以使用类型断言

也可以使用利用reflect.Value来完成同样的转换:

要注意的是reflect.Value.Int方法返回值是int64类型:

之所以先判断下Kind是否为int类型簇,是因为当不是对应类型时,Int方法会panic

当然还是类型断言比较简洁(当你确切知道底层类型时),如果用reflect.Value转换类型的话,会很繁琐

reflect.Value也支持其他的基本类型转换:

就不一一举例了

如果传递的底层类型是指针,我们可以通过Set方法簇来修改变量值:

除SetInt还有以下Set方法:

修改结构体字段的值:

同样得传递指针,然后通过Elem方法取得指向的值,才可以修改值(感兴趣的小伙伴可以自己试试不传递指针)

到这,可能有些小伙伴会有点confuse,比如FieldByName这个方法,要注意reflect.Type和reflect.Value都有,但返回值是不一样的:

所以要注意下它们的区别

Call方法调用函数:

要注意的是,Call方法接受和返回的参数都是[]reflect.Value:

CallSlice调用变参函数(variadic function):

CallSlice会将入参切片的最后一个元素作为函数的变参:

调用结构体的方法:

什么时候用反射?

到此,我们已经接触了大堆reflect包的示例代码,可以说是初步掌握了reflect包的使用。

这时要问自己一个问题:

什么时候用反射?反射特性虽然很强,但应该经常使用它吗?

这时可以引用Golang之父的一句话:

Clear is better than clever. Reflection is never clear.

简洁的代码比聪明的代码更好,而反射是不简洁的

反射在Golang中是非常强大而先进的一个概念,但应该非常小心的使用它。

使用反射时,写出简洁易懂且可维护性高的代码是很难的。

只有当反射是必要时,才去使用它,而且要非常小心











OK,Golang反射就介绍到这,希望对你有帮助~