1. 程式人生 > >Go語言之defer

Go語言之defer

defer關鍵字

defer和go一樣都是Go語言提供的關鍵字. defer用於資源的釋放, 會在函式返回之前進行呼叫. 要使用好defer最重要的是要理解return執行過程: 先給返回值賦值, 然後呼叫defer表示式, 最後才是返回到呼叫函式中. 理解了這句話, 關於defer的疑惑都能迎刃而解了.

例子

例一:

func f1() (result int) {
	defer func() {
		result++
	}()
	return 0
}

return時先將對result賦值0, 然後defer中對result++, 此時result=1; 最後返回時result=1,即呼叫函式獲得值2.

例二:

func f2() (r int) {
	t := 5
	defer func() {
		t = t + 5
	}()
	return t
}

return時先將t的值5賦值給r(值傳遞); 然後defer中對加5,此時t=10,r=5; 最後返回時r=5, 即呼叫函式獲得值5.

例三:

func f3() (r int) {
	defer func(r int) {
		r = r + 5
	}(r)
	return 1
}

return時先將1賦值給r; 然後呼叫defer時將r的值傳遞給defer函式, 注意defer函式中的r已經與函式f3返回的r不是一個變數(值傳遞), 因此r的修改不會影響f3返回值; 最後返回時r=1, 即呼叫函式獲得值1.

例四:

func addCounter() {
	for count := 0; count < 2; count++ {
		defer lock.Unlock()
		//do someThing
		lock.Lock()
	}
}

將解鎖放到defer中是為了防止執行任務(do someThing)時panic導致程式異常結束而未解鎖。實際執行時該例子會產生死鎖, 原因是(1) Muxtex不是可重入鎖; (2) defer會在函式結束時執行,而不是在每一輪for迴圈結束時執行。正確寫法如下:

func addCounter() {
	for count := 0; count < 2; count++ {
		doSomeThing()
	}
}

func doSomeThing() {
	lock.Lock()
    defer lock.Unlock()
    //do someThing
}