当前位置:网站首页>Deep understanding of golang - closures
Deep understanding of golang - closures
2022-07-27 00:55:00 【everyD_ struggle】
–
problem
Closure Is an entity composed of functions and their related reference environments ( namely : Closure = function + Citation environment ).
“ official ” The explanation is : So-called “ Closure ”, It's an expression that has many variables and an environment bound to them ( Usually a function ), So these variables are also part of the expression .
For example, below “ Fibonacci sequence ” Closure :
func fib() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}
Call the following
f00 := fib()
fmt.Println(f00(), f00(), f00(), f00(), f00())
The output is :1 1 2 3 5
golang How to achieve this kind of closure management in ?
Closure implementation
Let's divide closures first 3 Kinds of scenes :
There is no reference environment in the closure ( Variable life cycle is very short , Release after calling )
Reference global variables in closures ( The variable life cycle is the global variable life cycle )
Reference local variables in closures ( Variable life cycle is long , Do not release after calling , The next call will continue to reference )
Respectively for 3 Three scenarios are analyzed with the following code :
var y int
// The first scenario
func fib01() func() int {
return func() int {
a, b := 0, 1
a, b = b, a+b
return a
}
}
// The second scenario
func fib00() func() int {
return func() int {
y++
return y
}
}
// The third scenario
func fib3(x int) func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
x++
return a+x
}
}
Save the above file as closure.go, Then use assembly tools to generate assembly code . Compilation reference golang Kernel family – In depth understanding of plan9 assembly & practice
git:[email protected]:buptbill220/gotls.git
Generate the assembly with the following name :
go tool compile -S closure.go > closure.S
We turn on closure.S Find the corresponding function closure location
The first scenario fib01
And then find “”.fib01.func1
Closures are defined in the global area to code segments
"".fib01.func1·f SRODATA dupok size=8
We can see : This situation is a common function , Directly return the function address and call 
To help understand this implementation , We manually use assembly to call functions according to a function address
TEXT ·CallTest(SB),NOSPLIT,$0-8
MOVQ arg+0(FP), AX
CALL AX
RET
func call_test() {
fmt.Printf("call test")
}
func CallTest(uintptr)
x := call_test
CallTest(**(*(*uintptr))(unsafe.Pointer(&x)))
Results output :call test
The second scenario fib00
And then find “”.fib00.func1
y The location of
“”.y SNOPTRBSS size=8
We can see , The second scenario is also to return the address of the function closure , Just access global variables inside the closure , No extra work . Can match the scene 1 Summarized into a class
The third scenario fib3
Because there are many compilations , Split into 2 part 

And then find “”.fib3.func1
Through the above analysis , We can see , All reference local variables ,Golang Generating assembly is to help us create a copy of this variable on the heap , And the variable address and function closure form a structure , And pass the structure as the return value .
The structure form is as follows :
type FF struct {
F unitptr
B *int
A *int
X *int // If X yes string/[]int, So here should be *string,*[]int
}
This structure has a feature : The order of variables in the structure is just opposite to that of references in the function . This is because Golang In order to maintain the consistency of physical address sequence .
- The physical space of the stack increases in order from large to small , The order of addresses seen in the stack is x>a>b
- What we refer to is that the order of physical space growth on the heap is from small to large , In order to keep the order consistent with the physical address on the stack , The order of the generated structure is b、a、x
To help understand this implementation , We manually convert function closures into structures and output :
type FF struct {
F unitptr
b *int
a *int
x *int
}
f := fib3(0)
ptr := *(**FF)(unsafe.Pointer(&f))
fmt.Printf("ptr %v, %d, %d, %d\n", ptr, *ptr.a, *ptr.b, *ptr.x)
fmt.Println(f(), f(), f(), f(), f())
fmt.Printf("ptr %v, %d, %d, %d\n", ptr, *ptr.a, *ptr.b, *ptr.x)
Manually debug yourself
There is another feature here : The function closure itself accesses the variables of the reference environment through registers , The address of the structure will be placed in the register in advance before the closure call ( Put it here DX)
We can look at the code before the closure call :
summary
golang The function closure implementation of is mainly divided into 2 Middle scene :
There is no reference environment in the closure & Get reference global variables . In this case , Its implementation is a common function , Perform closure calls in the normal way of function calls .
Reference local variables in closures . In this case , Is the real closure ( function + Citation environment ), And with a struct{FuncAddr, LocalAddr3, LocalAddr2, LocalAddr1} Structure stores the closure , Wait until the closure is invoked , The structure address will be placed in a register in advance , Inside the closure, the variables of the reference environment are accessed through this register
边栏推荐
猜你喜欢

基于Flink实时项目:用户行为分析(三:网站总浏览量统计(PV))

Flink1.11 intervalJoin watermark生成,状态清理机制源码理解&Demo分析

Two methods of automated testing XSS vulnerabilities using burpsuite

基于Flink实时项目:用户行为分析(二:实时流量统计)

Golang切片make与new的区别
![[CISCN2019 华东南赛区]Double Secret](/img/51/9597968ff1747a67e10a70b785ee9f.png)
[CISCN2019 华东南赛区]Double Secret

Flink checkpoint源码理解

JSCORE day_02(7.1)

redis——缓存雪崩、缓存穿透、缓存击穿

DOM day_ 02 (7.8) web page production process, picture SRC attribute, carousel chart, custom attribute, tab bar, input box event, check operation, accessor syntax
随机推荐
Valueerror: the device should not be 'GPU', since paddepaddle is not compiled with CUDA
Flink 1.15实现 Sql 脚本从savepointh恢复数据
Promise基本用法 20211130
Search engine realizes keyword highlighting
箭头函数详解 2021-04-30
基于Flink实时计算Demo:用户行为分析(四:在一段时间内到底有多少不同的用户访问了网站(UV))
[watevrCTF-2019]Cookie Store
2022.7.16DAY606
14 web vulnerability: types of SQL injection and submission injection
[interview: concurrent Article 16: multithreading: detailed explanation of wait/notify] principle and wrong usage (false wake-up, etc.)
Detailed explanation of arrow function 2021-04-30
MySQL Article 1
[NCTF2019]SQLi
2022.7.10DAY602
Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=
Ah ah ah ah ah a
[CTF攻防世界] WEB区 关于备份的题目
6_ Gradient descent method
DOM day_ 04 (7.12) BOM, open new page (delayed opening), address bar operation, browser information reading, historical operation
Leetcode 302 weekly games