mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
ch3.6: fix typo
This commit is contained in:
parent
f475796c5c
commit
2dd023101c
@ -302,7 +302,7 @@ TEXT ·sum(SB), $16-16
|
|||||||
|
|
||||||
## 3.6.6 闭包函数
|
## 3.6.6 闭包函数
|
||||||
|
|
||||||
闭包函数是最强大的函数,因为闭包函数可以捕获外层局部作用域内部的变量,因此闭包函数本身就具有了状态。从理论上来说,全局的函数也是闭包函数的子集,只不过全局函数并没有捕获外层变量而已。
|
闭包函数是最强大的函数,因为闭包函数可以捕获外层局部作用域的局部变量,因此闭包函数本身就具有了状态。从理论上来说,全局的函数也是闭包函数的子集,只不过全局函数并没有捕获外层变量而已。
|
||||||
|
|
||||||
为了理解闭包函数如何工作,我们先构造如下的例子:
|
为了理解闭包函数如何工作,我们先构造如下的例子:
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
其中`NewTwiceFunClosure`函数返回一个闭包函数,返回的闭包函数捕获外层的`x`参数。返回的闭包函数在执行时,每次将捕获的外层变量乘以2之后再返回。在`main`函数中,首先以1作为参数调用`NewTwiceFunClosure`函数构造一个闭包函数,返回的闭包函数保存在`fnTwice`闭包函数类型的变量中。然后每次调用`fnTwice`闭包函数将返回翻倍后的结果,也就是:2,4,8。
|
其中`NewTwiceFunClosure`函数返回一个闭包函数对象,返回的闭包函数对象捕获了外层的`x`参数。返回的闭包函数对象在执行时,每次将捕获的外层变量乘以2之后再返回。在`main`函数中,首先以1作为参数调用`NewTwiceFunClosure`函数构造一个闭包函数,返回的闭包函数保存在`fnTwice`闭包函数类型的变量中。然后每次调用`fnTwice`闭包函数将返回翻倍后的结果,也就是:2,4,8。
|
||||||
|
|
||||||
上述的代码,从Go语言层面是非常容易理解的。但是闭包函数在汇编语言层面是如何工作的呢?下面我们尝试手工构造闭包函数来展示闭包的工作原理。首先是构造`FunTwiceClosure`结构体类型,用来表示闭包对象:
|
上述的代码,从Go语言层面是非常容易理解的。但是闭包函数在汇编语言层面是如何工作的呢?下面我们尝试手工构造闭包函数来展示闭包的工作原理。首先是构造`FunTwiceClosure`结构体类型,用来表示闭包对象:
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ func NewTwiceFunClosure(x int) func() int {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`FunTwiceClosure`结构体包含两个成员,第一个成员`F`表示闭包函数的函数指令的地址,第二个成员`X`表示闭包捕获的外部变量。如果闭包函数捕获了多个外部变量,那么`FunTwiceClosure`结构体也要做相应的调整。然后构造`FunTwiceClosure`结构体对象,也就是闭包函数对象。其中`asmFunTwiceClosureAddr`函数用于辅助获取闭包函数的函数指令的地址,采用汇编语言实现。最后通过`ptrToFunc`辅助函数将结构体指针转为闭包函数对象返回,该函数也是通过汇编语言实现。
|
`FunTwiceClosure`结构体包含两个成员,第一个成员`F`表示闭包函数的函数指令的地址,第二个成员`X`表示闭包捕获的外部变量。如果闭包函数捕获了多个外部变量,那么`FunTwiceClosure`结构体也要做相应的调整。然后构造`FunTwiceClosure`结构体对象,其实也就是闭包函数对象。其中`asmFunTwiceClosureAddr`函数用于辅助获取闭包函数的函数指令的地址,采用汇编语言实现。最后通过`ptrToFunc`辅助函数将结构体指针转为闭包函数对象返回,该函数也是通过汇编语言实现。
|
||||||
|
|
||||||
汇编语言实现了以下三个辅助函数:
|
汇编语言实现了以下三个辅助函数:
|
||||||
|
|
||||||
@ -380,7 +380,7 @@ TEXT ·asmFunTwiceClosureBody(SB), NOSPLIT|NEEDCTXT, $0-8
|
|||||||
RET
|
RET
|
||||||
```
|
```
|
||||||
|
|
||||||
其中`·ptrToFunc`和`·asmFunTwiceClosureAddr`函数的实现比较简单,我们不再详细描述。最重要的是`·asmFunTwiceClosureBody`函数的实现:它有一个`NEEDCTXT`标志。采用`NEEDCTXT`标志定义的函数表示需要一个上下文环境,在AMD64环境下是通过`DX`寄存器来传递这个上下文环境指针,也就是对应`FunTwiceClosure`结构体的指针。函数手写从`FunTwiceClosure`结构体对象取出之前捕获的`X`,将`X`乘以2之后写回内存,最后返回修改之后的`X`的值。
|
其中`·ptrToFunc`和`·asmFunTwiceClosureAddr`函数的实现比较简单,我们不再详细描述。最重要的是`·asmFunTwiceClosureBody`函数的实现:它有一个`NEEDCTXT`标志。采用`NEEDCTXT`标志定义的汇编函数表示需要一个上下文环境,在AMD64环境下是通过`DX`寄存器来传递这个上下文环境指针,也就是对应`FunTwiceClosure`结构体的指针。函数首先从`FunTwiceClosure`结构体对象取出之前捕获的`X`,将`X`乘以2之后写回内存,最后返回修改之后的`X`的值。
|
||||||
|
|
||||||
如果是在汇编语言中调用闭包函数,也可以遵循同样的流程:首先为构造闭包对象,其中保存捕获的外层变量;在调用闭包函数时首先要拿到闭包对象,用闭包对象初始化`DX`,然后从闭包对象中取出函数地址并用`CALL`指针调用。
|
如果是在汇编语言中调用闭包函数,也需要遵循同样的流程:首先为构造闭包对象,其中保存捕获的外层变量;在调用闭包函数时首先要拿到闭包对象,用闭包对象初始化`DX`,然后从闭包对象中取出函数地址并用通过`CALL`指令调用。
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user