Go语言的反射原理(1)

本文根据The Go Blog翻译,原文英文版:https://blog.golang.org/laws-of-reflection

介绍

反射是一种程序获取自身结构(特殊是数据类型)的机制。
本文将阐述Go语言中的反射机制是如何工作的。每一种语言的反射机制是不同的,有些语言支持反射,有些语言则根本不支持。下文中所说的“反射”即是指Go语言的反射。

类型和接口interfact

反射是建立在类型系统的基础上,在正式介绍反射之前,本文将首先介绍Go语言的类型系统,特殊是interface类型,因为interface与反射联系非常紧密。
Go语言的类型是静态的,每一个变量都有一种静态类型,也就是说,在编译的时候变量类型就已经确定了,例如int、float32、*MyType、[]bytet等等。如果我们声明

type MyInt int

var i int
var j MyInt

那么i的类型就是int,j的类型就是MyInt.尽管变量i和变量j的底层类型是相同的,但是属于他们仍属于不同的静态类型,两者不能直接相互赋值(除非强制转换)。

Go语言中接口interface是非常重要的一种类型,该类型表示一组固定的方法集。只要实现了该interface类型的方法,interface变量就可以用于存储任意具体类型的变量(包括非interface类型变量)。比较常见的例子就是io.Reader和io.Witer,这两个类型定义在io.package中:

// Reader方法封装了基础的读方法
type Reader interfcae {
  Read(p []byte) (n int, err errror)
}

// Writer方法封装了基础的写方法
type Writer interface {
  Write(p []bype) (n int, err error)
}

任何实现了Read(或Write)方法的类型就可以说是实现了io.Reader(或io.Writer)接口。结论就是:io.Reader接口类型可以承载实现该Read方法的任意类型。

var r io.Reader
r = os.Stdin
r = bufio.NewReader(r)
r = new(bytes.Buffer)

需要明确的是,不管变量r承载的是什么具体类型的变量,r的类型始终都是io.Reader,因为Go语言是静态类型语言,变量r的静态类型就是io.Reader.

还有一个特别重要的接口类型就是空接口:

Interface{}

它该接口包含的方法为空,并且它可以表示任意类型,因为所有的类型都包含0个或多个方法。
有些人说Go的接口类型interface是动态的,这其实是不对的。Go语言中所有接口类型都是静态类型:一个接口类型的变量始终都是一样的类型,尽管在运行时变量存储的值可以变成其它类型,但是这些值都必须符合该接口的原型。

接口interfcae的表示

Russ Cox已经在博客中(原文链接:https://research.swtch.com/interfaces)详细介绍了Go语言中接口类型interface的表示,这里没必要全文复述,但是还是有必要简单的总结一下。
接口变量存储一对值:具体类型的值value,以及该类型的描述符type。更准确地说,值value是实现了该接口的底层数据项,类型type描述了该数据项的完整类型。举例来说:

var r io.Reader
tty, err =:= os.OpenFile(/dev/tty”, os.O_RDWR, 0)
if err != nil {
  return nil, err
}
r = tty

r包含(value, type)键值对(tty, *os.File).需要注意的是,类型os.File实现了不仅仅是Read方法。尽管变量r只向外提供Read方法,但是实则携带了所有os.File类型的所有信息。这也是就为什么我们还可以这样写:

var w io.Writer
w = r.(io.Writer)

上述赋值表达是也是合法,这表明了r同时也实现了io.Writer,所以我们才可以将r赋值给w。这次赋值之后,w将和r一样,包含键值对(tty, *os.File)。由于Interface是静态类型的,这决定了该接口变量可以调用哪些方法要,即便是具体值内部可以包含更多的方法。

接着,我们还可以这样:

var empty interface{}
empty = w

同样,我们的空接口empty也包含同样的键值对(tty, *os.File)。可以得出结论:一个空方法interface可以承载任何值,并且包含该具体值所有的信息。
另外一个重要方面就是:接口的键值对总是表示成(value,concrete type)的形式,并且一定不能是(value, interface type)的形式。因为接口类型不能存储接口类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值