知识点1: defer
defer知识点总结
官方文档
https://golang.org/ref/spec#Defer_statements
考点1:defer语句的执行顺序
defer语句的执行顺序如同栈一样,先进后出
- 例1
// prints 3 2 1 0 before surrounding function returns
for i := 0; i <= 3; i++ {
defer fmt.Print(i)
}
解答:
defer语句的执行顺序是是先进后出
输出 3 2 1 0
考点1 plus:defer语句与panic语句执行顺序
panic 需要等defer 结束后才会向上传递,所以会先执行defer语句然后执行panic
- 例2
func defer_call() {
defer func() { fmt.Println("打印前") }()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
panic("触发异常")
}
解答:
defer 是后进先出。
panic 需要等defer 结束后才会向上传递。 出现panic恐慌时候,会先按照defer的后入先出的顺序执行,最后才会执行panic。
打印后
打印中
打印前
panic: 触发异常
考点2: defer语句与return语句
注意return语句其实不是一个原子语句,可以拆分成 赋值语句与return 空 语句,赋值语句会在defer之前执行,而return 空语句会在defer执行完之后再执行。
- 例1
// f returns 42
func f() (result int) {
defer func() {
// result is accessed after it was set to 6 by the return statement
result *= 7
}()
return 6
}
解答:
该题目可以改写为
func f() (result int) {
//赋值语
result = 6
defer func() {
result *= 7
}()
//return 空语句
return
}
这样就很容易看出来了,返回值其实是42而不是6
- 例2
func f() (result int) {
defer func() {
result++
}()
return 0
}
解答:
返回值为1
考点3: defer语句与闭包
- 例1
func f() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
解答:
注意f()的入参是r, 而defer函数里的变量为t
拆分return t,可以得到 r=t语句,而且r并没有传入defer func()中,所以return的时候返回的是t的原始值,即5
- 例2
func f() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
解答:
拆分retun 1, 可以得到 r = 1, 然后r作为参数传入了defer func(r int)中, 所以会执行r = r + 5语句,然后再执行return语句。 即最后返回值为 6
考点4: defer保存副本
- 例1
func hello(i int){
fmt.Println(i)
}
func main(){
i := 5
defer hello(i)
i = i + 10
}
输出:5
这个例子中,hello()函数的参数在执行defer语句的时候会保存一份副本。在实际调用hello()函数时用,所以是5