一、defer和go后面的函数
先来看defer
package main
import "fmt"
func main() {
var i int = 1
defer fmt.Println("result =>",func() int { return i * 2 }())
i++
}
输出结果:
result => 2
看这个代码会疑惑结果为何不是result=>4 呢??
原因是 调用任何一个函数前都要先对函数的参数进行求值,之后再进入函数体,只不过defer将进入函数执行的过程推迟到defer的调用方退出之前了
二、go
package main
import (
"fmt"
"time"
)
func main() {
var i int = 1
go fmt.Println("result =>",func() int { return i * 2 }())
i++
time.Sleep(3*time.Second)
}
输出结果:
result => 2
所以,无论是go关键字还是defer关键字,在代码执行到它们时, 编译器都要为它们后面的函数准备好函数调用的参数堆栈,要确定的参数值和参数型大小。这样一来就得去求值:对它们后面的函数的参数进行 求值。
二、闭包函数
package main
import "fmt"
func main() {
/*
无参闭包
执行函数体是用外部的引用
*/
var i int = 1
defer func() {
fmt.Println("result0 =>", func() int { return i * 2 }())//用的是i的引用
}()
i++
/*
有参闭包
先计算此时函数的参数列表,也是引用,但是 是此时的引用
执行函数体时用直接用当时计算出来的参数
*/
var ii int = 1
defer func(ii int){//此时计算出ii得1
fmt.Println("result1 =>", func() int { return ii * 2 }())//用的是此时外部的ii的值,与defer fmt.Println("result =>",func() int { return i * 2 }())等价
}(ii)
ii++
}
输出结果:
result1 => 2
result0 => 4
无参闭包
执行函数体是用外部的引用
有参闭包
先计算此时函数的参数列表,也是引用,但是,是此时的引用,执行函数体时用直接用当时计算出来的参数