Go语言defer
2021-02-20 03:24
标签:turn 例子 显示 Go语言 并且 一点 延迟 函数调用 赋值 函数中被defer关键字声明的语句会被延迟执行,延迟到函数结束之前才执行。 首先对于函数中的return语句,它是由两步组成,而非一个原子操作: return=赋值给返回值+返回 如果传入的参数是5,这个函数的返回值是5,在函数最后返回的时候,首先创建一个匿名变量作为返回值,并且将x的值赋值给这个匿名变量,然后defer的延迟执行函数将x+1,但是此时已经和返回值没有关系了,因为x和返回值是两个变量,最后就是执行RET返回,所以一个函数的return语句是分两步执行,然后defer声明的语句则延迟到这两句之间执行 如果这个时候传入的参数是5,这个函数的返回值是6,此时我们已经将返回值由匿名变量显示的变为变量y,所以执行的过程为首先将x的赋值给y,此时y的值是5,然后执行defer声明的语句,将y++,所以返回值这个变量的值变为了6,最后执行RET返回,因此最后的返回值是6. 这个函数的返回值是0,首先返回值y的类型是int,默认值是0,所以在返回的时候首先给y赋值为0,然后执行defer声明的函数,此时采用的是值传递,所以这个函数中的y其实是函数返回值的那个y的副本,他们是两个变量,所以此时修改y不能对函数返回值的那个y起作用,最后再返回。 这个函数最后的返回值是6,过程如下,首先对函数的返回值y赋值为5,然后执行defer声明的函数,这个函数的入口参数是一个指针,所以采用的是地址传递而不是值传递,上面那个函数就是把返回值y的地址传入了defer的函数,所以最后修改了返回值y的值,y+1,所以最后返回值是6 然后再看一个比较复杂的例子,这个例子说明了在对defer的语句进行压栈的时候,会保存当前的状态: 从上面的代码可以看出两点,defer声明的函数内部如果还有函数调用(比如参数是另一个函数),那么会首先执行那个函数,并且得到一个结果,然后将这个结果压栈,另一点就是对于defer函数的变量,会在defer被压栈的时候保存这些变量当前的值,defer语句被压栈以后,再修改这些变量的值,并不会对defer语句中的这些变量产生影响。 Go语言defer 标签:turn 例子 显示 Go语言 并且 一点 延迟 函数调用 赋值 原文地址:https://www.cnblogs.com/gyyyl/p/12683830.htmlfunc f1(x int) int { //x=5
defer func() {
x++
}()
return x
}
func f1(x int) (y int) { //x=5
defer func() {
y++
}()
return x
}
func f1() (y int) {
defer func(y int) {
y++
}(5)
return y
}
func f1() (y int) {
defer func(y *int) {
*y++
}(&y)
return 5
}
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
a, b := 1, 2
// a=1
// b=2
defer calc("1", a, calc("10", a, b))
// defer的函数中还调用了函数,所以在对这条语句压栈的时候,会先执行内层的calc函数
// calc("10",1,2)==>输出"10" 1 2 3
// 然后对defer语句当前的状态压栈,当前a=1
// 所以压栈的语句为:
// defer calc("1",1,3)
a = 0
// a=0
defer calc("2", a, calc("20", a, b))
// defer的函数中还调用了函数,所以在对这条语句压栈的时候,会先执行内层的calc函数
// calc("20",0,2)==>输出"20" 0 2 2
// 然后对defer语句当前的状态压栈,当前a=0
// 所以压栈的语句为:
// defer calc("2",0,2)
b = 1
// b=1
// 然后执行压栈的defer语句
// calc("2",0,2)==>输出"2" 0 2 2
// calc("1",1,3)==>输出"1" 1 3 4
// 所以最后的输出结果是:
// "10" 1 2 3
// "20" 0 2 2
// "2" 0 2 2
// "1" 1 3 4
}