兄弟連go教程(15)函式 - 延遲呼叫

尹成發表於2018-07-04
關鍵字 defer ⽤用於註冊延遲調⽤用。這些調⽤用直到 ret 前才被執⾏行,通常⽤用於釋放資源或錯
誤處理。
func test() error {
f, err := os.Create("test.txt")
if err != nil { return err }
defer f.Close() // 註冊調⽤用,⽽而不是註冊函式。必須提供引數,哪怕為空。
f.WriteString("Hello, World!")
return nil
}


多個 defer 註冊,按 FILO 次序執⾏行。哪怕函式或某個延遲調⽤用發⽣生錯誤,這些調⽤用依舊
會被執⾏行。
func test(x int) {
defer println("a")
defer println("b")
defer func() {
println(100 / x) // div0 異常未被捕獲,逐步往外傳遞,最終終⽌止程式。
}()
defer println("c")
}
func main() {
test(0)
}


輸出:
c
b
a
panic: runtime error: integer divide by zero



延遲調⽤用引數在註冊時求值或複製,可⽤用指標或閉包 "延遲" 讀取。
func test() {
x, y := 10, 20
defer func(i int) {
println("defer:", i, y) // y 閉包引⽤用

}(x) // x 被複制
x += 10
y += 100
println("x =", x, "y =", y)
}


輸出:
x = 20 y = 120
defer: 10 120


濫⽤用 defer 可能會導致效能問題,尤其是在⼀一個 "⼤大迴圈" ⾥裡。
var lock sync.Mutex
func test() {
lock.Lock()
lock.Unlock()
}
func testdefer() {
lock.Lock()
defer lock.Unlock()
}
func BenchmarkTest(b *testing.B) {
for i := 0; i < b.N; i++ {
test()
}
}
func BenchmarkTestDefer(b *testing.B) {
for i := 0; i < b.N; i++ {
testdefer()
}
}


輸出:
BenchmarkTest? 50000000 43 ns/op
BenchmarkTestDefer 20000000 128 ns/op

尹成老師

QQ77025077 

微信18510341407

所有視訊在尹成學院

www.yinchengxueyuan.com

尹成百度雲請聯絡QQ475318423



相關文章