defer vs return

pardon110發表於2019-12-02

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返回值,而匿名則不會。

細細思之,這種安排也合情合理,誰還會將一次性手紙重複利用?
匿名變數顧名思義,用過即丟,不會再理了。具名,為什麼要有名字,不就是為了複用。
既然是複用,再次用之怎能不可改變?否則安排就沒意義了

擴充

想想如果返回型別是指標型別,有名與無名返回型別是否有區別?

相關文章