上次學完 for loop,這次接著官方教學往後看,第一個是 switch,switch 倒是沒有太大區別,值得一提的是不用 break,也可以不用條件式 (視為 true):
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
}
後面的 defer 就很有意思了,根據官方說法:
A defer statement defers the execution of a function until the surrounding function returns.
一開始以為是所在的 function 結束後執行 defer 後面的動作,但試了一下並不是,精確地來說是「 function return 前執行」。
那這兩種有什麼區別?
後者可以透過 defer 更改 function return 的值,前者就完全辦不到了...
例如這個 function,最終回傳的是 2:
func Test() (x int) {
defer func() {
x++
}()
return 1
}
並且 defer 是以 stack(LIFO) 儲存,後加入的會先做
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
3
2
1
接著就出現了有趣的事,本來想複習一下各種 function 的寫法,意外發生了。
func Test() int {
x := 1
defer func() {
x++
}()
return x
}
原本以為這東西跟上面一樣會回傳 2,結果是回傳 1...
一瞬間腦袋蹦出了好幾個問號????
難道 Named Return Value 跟普通變數的行為是不同的嗎????
邊查邊跟 GPT 討論,發現這牽扯到 Go 的行為,口語上似乎會叫成 "return slot"(GPT 講的),雖然用這個詞查不到這個行為,不過就先這樣了,我只想搞懂行為本身...
若當前這個 function 沒有 Named Return Value,Go 在執行時,會有「隱藏的變數用來預先存放」要 return 的值,所以假設 function 長這樣:
func Test() int {
x := 1
defer func() {
x++
}()
return x
}
實際上 return 的並不是 x,而是值跟 x 一樣的另一個變數,可能是 y, z...bruh bruh
但若 function 有 Named Return Value,這個 Named Return Value 就會直接是核心用來存放的那個變數,所以 defer 在操作時會確實操作到核心準備 return 的變數,也就可以變更 return 的值了!
終於是摸到了一些 Go 的語言特性之一,感覺光 defer 就可以變出好多花樣,不過學完 defer 腦袋也昏昏的了,今天就先這樣好了...