interfaceunsafe.Pointerinterfaceunsafe.Pointer

(本文目前使用的Go环境是Go 1.12.9)

interface回顾

首先我们简单的回顾一下interface的结构,总体上是:

ifaceefaceinterface{}
eface

iface

静态类型(static interface type)和动态混合类型(dynamic concrete type)

Go语言中,每个变量都有唯一个 静态类型 ,这个类型是编译阶段就可以确定的。有的变量可能除了静态类型之外,还会有 动态混合类型

例如以下例子:

iface
var r io.Reader

*os.Filer = tty

eface
var empty interface{}

empty = tty

但是记住:虽然有 动态混合类型 ,但是对外”表现”依然是静态类型。

Go反射简介

Go反射有三大法则:

//接口数据  =====》 反射对象
1. Reflection goes from interface value to reflection object.
//反射对象 ===> 接口数据
2. Reflection goes from reflection object to interface value.
// 倘若数据可更改,可通过反射对象来修改它
3. To modify a reflection object, the value must be settable.

Go 的反射就是对以上三项法则的实现。

TypeValueTypeValue

Type:

Value:

你会发现反射的实现和interface的组成很相似,都是由“类型”和“数据值”构成,但是值得注意的是:interface的“类型”和“数据值”是在“一起的”,而反射的“类型”和“数据值”是分开的。

TypeValue

Go中的反射,在使用中最核心的就两个函数:

  • reflect.TypeOf(x)
  • reflect.ValueOf(x)
TypeValue反射对象

Reflection goes from interface value to reflection object(法则一)

TypeValue

事例代码:

ValueType

所以,法则一的图应为:

Reflection goes from reflection object to interface value.(法则二)

给定的反射对象,可以转化为某种类型的数据对象。即法则一的逆向。

Type

承接法则一的代码:

To modify a reflection object, the value must be settable.(法则三)

法则三是说:通过反射对象,可以修改原数据中的内容。

ValueTypeValue
Value

这段代码20行会报一个panic

vsettable
ValueCanSet()
CanSet()

如何通过反射对象来修改原数据对象的值呢?

如何才能可以通过反射对象来修改原数据对象的值或者说为什么不能设置呢?

原因简单且纯粹:在Go中,任何函数的参数都是值的拷贝,而非原数据。

reflect.ValueOf()settableCanSet()

那如何修改呢?

首先,在Go中要想让函数“有副作用“,传值必须传指针类型的。

此时还不行,因为这样反射对象对应的是原数据对象的指针类型,必须要拿到当前类型的值类型(*v),如何做?

Elem()

看以上代码,就可以修改原数据了。

反射原理

Typevalue

反射会不会是比着interface来实现的?

反射是什么意思?反射的意思是在运行时,能够动态知道给定数据对象的类型和结构,并有机会修改它!

现在一个数据对象,如何判断它是什么结构?

数据interface中保存有结构数据呀,只要想办法拿到该数据对应的内存地址,然后把该数据转成interface,通过查看interface中的类型结构,就可以知道该数据的结构了呀~

其实以上就是Go反射通俗的原理。

图可以展示为:

unsafe.Pointer

源码部分 (以下部分可以忽略,是我在查阅代码时候遇到的一点点坑。)

我们来看看具体的源码:源码在”GO SDK/src/refelct“包中,具体主要是包中的”type.go”和”value.go”这两个文件。

reflect.ValueOf()reflect.TypeOf()
reflect.TypeOf()
TypeemptyInterface

分别看看这两者的代码:

emptyInterface
efaceifaceefaceiface

经过查阅代码,发现:

efaceifaceemptyInterfacenonEmptyInterface

总结

以上所述是小编给大家介绍的图文详解go语言反射实现原理,希望对大家有所帮助!