Go语言函数切片的底层存储结构及实现原理是什么?
Go中
[]func()切片的底层存储是什么? 我在官方文档里没找到相关答案。给定如下函数切片:
var funcs []func()
它的底层支撑数组到底存的是什么?
一开始我以为是函数指针数组,但后来发现可以执行如下操作:
funcs = append(funcs, f.SomeFunc) funcs[0]() // 调用f的SomeFunc方法
其中f是任意定义了接收者方法的类型,那它的底层实现究竟是什么?
示例程序
package main import "fmt" func PrintStandalone() { fmt.Println("Standalone") } type Point struct { x int y int } func (p *Point) PrintPoint() { fmt.Println("X: ", p.x, " Y: ", p.y) } type Coordinate struct { lat int long int } func (c Coordinate) PrintCoordinate() { fmt.Println("Lat: ", c.lat, " Long: ", c.long) } func main() { p := Point{x: 1, y: 2} c := Coordinate{lat: 3, long: 4} var funcs []func() funcs = append(funcs, PrintStandalone) funcs = append(funcs, p.PrintPoint) funcs = append(funcs, c.PrintCoordinate) for _, fn := range funcs { fn() } p = Point{x: 5, y: 6} c = Coordinate{lat: 7, long: 8} for _, fn := range funcs { fn() } }
运行输出
Standalone X: 1 Y: 2 Lat: 3 Long: 4 Standalone X: 5 Y: 6 Lat: 3 Long: 4
底层实现分析
从输出结果能看出:
- 当方法的接收者是指针类型时,后续修改原对象的值后,调用切片里的函数会反映新值,说明此时切片存储的函数值绑定了原对象的指针引用;
- 当方法的接收者是值类型时,修改原对象后,切片里的函数调用仍然使用旧值,说明此时切片存储的函数值绑定了原对象的副本。
实际上,Go里的func()是函数值(function value),它并非简单的函数指针,而是包含两部分数据:
- 指向实际函数代码的指针;
- 绑定的上下文数据(比如方法的接收者)。
对于普通独立函数,函数值只需要存储函数代码指针;对于绑定了接收者的方法,Go会自动将其转换为包含接收者(指针或值副本)的函数值,相当于隐式生成了一个闭包,把接收者作为上下文保存下来。
所以[]func()切片的底层支撑数组,存储的是一个个函数值对象,每个对象都包含函数代码指针和对应的上下文数据。
内容的提问来源于stack exchange,提问作者SRNissen
相关产品推荐
相关产品推荐

