golang defer 函数参数是立即求值

324 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

 在golang中,defer是在函数结束时调用,但是defer 函数参数确是立即求值的。请看如下代码:

package main
import "fmt"
func world() string {
	fmt.Println("1.world is running")
	return "world"
}

func hello(){
	defer func(s string){
		fmt.Println("3.hello is in defer:", s)
	}(world()) //这里world会立即求值

	fmt.Println("2.hello is running")

}
func main(){
	hello()
}

go run defer.go 
1.world is running
2.hello is running
3.hello is in defer: world

参数求值顺序也是自然的从左向右啦

package main
import "fmt"
func world() string {
	fmt.Println("1.world is running")
	return "world"
}
func world2() string {
	fmt.Println("2.world2 is running")
	return "world2"
}
func hello(){
	defer func(s string, s2 string){
		fmt.Println("4.hello is in defer:", s, s2)
	}(world(), world2())

	fmt.Println("3.hello is running")

}
func main(){
	hello()
}

 go run defer.go 
1.world is running
2.world2 is running
3.hello is running
4.hello is in defer: world world2

函数内装饰对局部变量是引用,所以defer里会受影响

package main
import "fmt"
func world() string {
	fmt.Println("1.world is running")
	return "world"
}
func world2(n int) string {
	fmt.Println("2.world2 is running")
	return fmt.Sprintf("world2.%d", n)
}
func hello(){
	n := 10
	defer func(s string, s2 string){
		fmt.Println("4.hello is in defer:", s, s2)
	}(world(), world2(n)) //此处n已经确定,n是拷贝确定
	defer func(){
		fmt.Println("inner defer:", n)  //n是引用,会受到下面的影响
	}()
	n = 20 //此修改不影响第一个defer闭包里的n,但是影响第二个

	fmt.Println("3.hello is running")

}
func main(){
	hello()
}

go run defer.go 
1.world is running
2.world2 is running
3.hello is running
inner defer: 20
4.hello is in defer: world world2.10

\