知識(shí)點(diǎn)1: defer
defer知識(shí)點(diǎn)總結(jié)
官方文檔
https://golang.org/ref/spec#Defer_statements
考點(diǎn)1:defer語(yǔ)句的執(zhí)行順序
defer語(yǔ)句的執(zhí)行順序如同棧一樣黔姜,先進(jìn)后出
- 例1
// prints 3 2 1 0 before surrounding function returns
for i := 0; i <= 3; i++ {
defer fmt.Print(i)
}
解答:
defer語(yǔ)句的執(zhí)行順序是是先進(jìn)后出
輸出 3 2 1 0
考點(diǎn)1 plus:defer語(yǔ)句與panic語(yǔ)句執(zhí)行順序
panic 需要等defer 結(jié)束后才會(huì)向上傳遞膳沽,所以會(huì)先執(zhí)行defer語(yǔ)句然后執(zhí)行panic
- 例2
func defer_call() {
defer func() { fmt.Println("打印前") }()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
panic("觸發(fā)異常")
}
解答:
defer 是后進(jìn)先出。
panic 需要等defer 結(jié)束后才會(huì)向上傳遞潭陪。 出現(xiàn)panic恐慌時(shí)候钢拧,會(huì)先按照defer的后入先出的順序執(zhí)行蟹漓,最后才會(huì)執(zhí)行panic。
打印后
打印中
打印前
panic: 觸發(fā)異常
考點(diǎn)2: defer語(yǔ)句與return語(yǔ)句
注意return語(yǔ)句其實(shí)不是一個(gè)原子語(yǔ)句源内,可以拆分成 賦值語(yǔ)句與return 空 語(yǔ)句葡粒,賦值語(yǔ)句會(huì)在defer之前執(zhí)行,而return 空語(yǔ)句會(huì)在defer執(zhí)行完之后再執(zhí)行膜钓。
- 例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) {
//賦值語(yǔ)
result = 6
defer func() {
result *= 7
}()
//return 空語(yǔ)句
return
}
這樣就很容易看出來了嗽交,返回值其實(shí)是42而不是6
- 例2
func f() (result int) {
defer func() {
result++
}()
return 0
}
解答:
返回值為1
考點(diǎn)3: defer語(yǔ)句與閉包
- 例1
func f() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
解答:
注意f()的入?yún)⑹莚, 而defer函數(shù)里的變量為t
拆分return t,可以得到 r=t語(yǔ)句颂斜,而且r并沒有傳入defer func()中夫壁,所以return的時(shí)候返回的是t的原始值,即5
- 例2
func f() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
解答:
拆分retun 1沃疮, 可以得到 r = 1, 然后r作為參數(shù)傳入了defer func(r int)中, 所以會(huì)執(zhí)行r = r + 5語(yǔ)句盒让,然后再執(zhí)行return語(yǔ)句。 即最后返回值為 6
考點(diǎn)4: defer保存副本
- 例1
func hello(i int){
fmt.Println(i)
}
func main(){
i := 5
defer hello(i)
i = i + 10
}
輸出:5
這個(gè)例子中司蔬,hello()函數(shù)的參數(shù)在執(zhí)行defer語(yǔ)句的時(shí)候會(huì)保存一份副本邑茄。在實(shí)際調(diào)用hello()函數(shù)時(shí)用,所以是5