闭包的本质其实是扩展
用匿名函数作为函数的返回值,可以扩展该函数的定义范围,该函数和匿名函数所组成的整体称为闭包
其特点
- 闭包的返回值为匿名函数
- 定义时匿名函数嵌套在闭包的内部
- 匿名函数引用了自身的外部变量x,即外层函数除了匿名函数外所定义的参数
- 闭包中的参数x是安全的变量,只有内部函数才能访问
func makeAdder(x int) func(int) int {
return func(y int) int { return x + y }
}
func main() {
fmt.Println(makeAdder(5)(1))//定义makeAdder的参数,再定义匿名函数的参数
}
输出:6 //5+1
fmt.Println(makeAdder(makeAdder(5)(1))(3))
输出:9 //5+1+3
函数回调
函数可以作为其他函数的参数进行传递,然后在其他函数内调用
func add(a, b int) {
fmt.Printf("%d+%d=%d\n", a, b, a+b)
}
func callback(x int, f func(int, int)) { //f的数据结构是函数
f(x, 2) //实际上是add(x,2) multi(x,2)
}
func multi(a, b int) {
fmt.Printf("%d*%d=%d\n", a, b, a*b)
}
func main() {
callback(1, add)
callback(1, multi) //定义参数x=1
}
延迟执行
无论该语句是否错误,都会在编译结束之前才被执行
正常情况
func main() {
fmt.Println("hello world")
fmt.Println("bye bye world")
}
hello world
bye bye world
延迟执行后
func main() {
defer fmt.Println("hello world")
fmt.Println("bye bye world")
}
bye bye world
hello world
用于数据清理工作,保证代码结构清晰,避免遗忘
srcFile,err:=os.Open(srcName)
defer srcFile.Close()//使用文件句柄时,避免在最后忘记关闭
注:多个defer时,执行顺序为逆序
defer fmt.Println("1111") // 输出:1
defer fmt.Println("111") // 11
defer fmt.Println("11") // 111
defer fmt.Println("1") // 1111
异常恢复机制
func main() {
f(101)
}
func f(x int) {
if x > 100 {
panic("参数越界") //panic捕获到异常情况
} else {
fmt.Println("函数调用成功")
}
}
panic: 参数越界
错误: 进程退出代码 2.
func main() {
defer func() {
err := recover() //recover返回错误,err是一种错误类型
if err != nil { //nil=null,如果捕获到的错误不为空
fmt.Println("异常,原因是:", err)
} else {
fmt.Println("正常退出")
}
}()//注意括号
f(101)
}
func f(x int) {
if x > 100 {
panic("参数越界") //panic捕获到异常情况
} else {
fmt.Println("函数调用成功")
}
}
异常,原因是: 参数越界
成功: 进程退出代码 0.