A defer statement defers the execution of a function until the surrounding function returns.
推遲執行defer的敘述式,盡可能地拖拖拖等等等,直到目前所在的func打烊結束要回傳時才做事。
defer是延遲執行的意思,主要用於宣告function結束前的動作
延遲執行的意思如下
package main
import (
"fmt"
)
var a = 50
func main() {
defer add_a()
fmt.Println(a)
}
func add_a() {
a += 100
}
執行後結果如下
50
你可以發現我們是先執行Println
才執行add_a()
程式會用到defer主要是需要拖延的時效性,類似鬧鐘能做到提醒的作用。
常用的場合如下:
像是把使用在讀檔後的關檔,這樣也不會忘記。
f, err := os.Open("test.txt")
if err != nil {
return err
}
defer f.Close()
也常運用在關閉channel
及 關閉DB
之中。
db, err := sql.Open("mysql", "USER:PASSWORD@/DB")
if err != nil {
log.Fatalln(err)
}
defer db.Close()
兩個defer執行的優先順序,為了要貫徹拖延的行為,越早分派的任務要越晚達成才行。
package main
import (
"fmt"
)
func main() {
defer print1()
defer print2()
}
func print1() {
fmt.Println("p1")
}
func print2() {
fmt.Println("p2")
}
執行後可得以下結果
p2
p1
package main
import (
"fmt"
)
func main() {
assign2(50)
}
func assign2(a int) int {
defer fmt.Println(a)
a = 100
return a
}
執行後可得以下結果
50
package main
import (
"fmt"
)
func main() {
assign1(50)
}
func assign1(a int) int {
a = 100
defer fmt.Println(a)
return a
}
執行後可得以下結果
100
package main
import (
"fmt"
"os"
)
func main() {
defer func() {
fmt.Println("output")
}()
os.Exit(0)
}
執行後可得以下結果
由於程式先執行了os.Exit(0)
,導致後面的defer
不會被執行。
package main
import (
"fmt"
)
func main() {
fmt.Println(func1())
}
func func1() int {
var a int
defer func() {
a = 100
}()
return a
}
執行後可得以下結果
0
func main() {
fmt.Println(func2())
}
func func2() (a int) {
a = 50
defer func() {
a = 100
}()
return a
}
執行後可得以下結果
100
看得出上述兩個範例的差異了麻?
差別在於一個func1
不指定要回傳哪個int
變數,但func2
指定要回傳a
變數!
也因此,func1
在直接return
的時候,由於並未指定要a
,因此defer
就讓return
先執行。
但func2
指定要a變數了,因此defer
發現它必須要執行完賦予a
值的任務才能讓他return
defer是個很簡單的觀念,但裡頭卻包含著許許多多較不直觀的地雷,也因此特意開一章節來替大家釐清排雷! 希望以後不會誤踩地雷。