defer 看起來與try...catch 類似,其實有許多不為人知的小技巧
defer
官方行文defer先進後出,對return進行一些掃尾工作。這意味著使用該函式在返回值之前,defer函式內是可以訪問使用defer的函式內任意變數。那麼問題來了,在defer函式內對所在函式變數進行修改,會影響返回的結果嗎?
碼說
示例展示了兩個使用defer的函式。用匿名返回型別,與具名返回型別函式,猜猜結果有無變化?
package main
import "fmt"
func main() {
fmt.Println("tstring return: ", tstring())
fmt.Println("tstring1 return: ", tstring1())
}
func tstring() string {
s := "a_"
defer func() {
s = s + "a"
fmt.Println("defer: ", s)
}()
return s
}
func tstring1() (s string) {
defer func() {
s = s + "b"
fmt.Println("defer1: ", s)
}()
return s
}
測試
程式碼驗證
vagrant@homestead go run test.go
defer: a_a
tstring return: a_
defer1: b
tstring1 return: b
結論
是不是很詭異?具名返回值型別時,結合defer可以修改return返回值,而匿名則不會。
細細思之,這種安排也合情合理,誰還會將一次性手紙重複利用?
匿名變數顧名思義,用過即丟,不會再理了。具名,為什麼要有名字,不就是為了複用。
既然是複用,再次用之怎能不可改變?否則安排就沒意義了
擴充
想想如果返回型別是指標型別,有名與無名返回型別是否有區別?