在Go語言當中,沒有例外處理機制,C
、Java
中常見的try...catch
在Go當中沒有實做出來,而是鼓勵以error
的方式去做錯誤檢查,會看到許多套件的方法都是以(target, error)
的方式回傳值,而開發時Go也提供了defer
、panic
、recover
去做錯誤處理。
延遲執行,可將函示延遲至return
前一刻才執行,舉個例子的話
package main
import "fmt"
func deferFunc() {
fmt.Println("有人提到倉鼠嗎?")
}
func main() {
defer deferFunc()
fmt.Println("早安哪")
}
output:
早安哪
有人提到倉鼠嗎?
會發現defer
的函式被延遲到最後一刻才執行了
defer
是將待執行的程式以stack
方式儲存,stack
屬於後進先出的容器,在使用上要多注意。
package main
import "fmt"
func main() {
defer fmt.Println("0")
defer fmt.Println("1")
defer fmt.Println("2")
fmt.Println("Hello !")
}
output:
Hello !
2
1
0
舉一個讀取檔案的例子,看看下面的例子,若偵測到錯誤的話
func main() {
f, err := os.Open("/tmp/dat")
if err != nil {
fmt.Println(err)
} else {
a, err := f.Read()
// .
// 正常執行
// .
f.Close()
}
}
看起來沒什麼問題對吧?有open
有close
,但這支程式有問題的點在於,若正常執行中出現了panic
類的錯誤,f.Close()
就不會被執行到了。
panic
是Go當中的另一種錯誤處理方式,會直接中斷目前的函式執行,並執行defer
中的程式,因此若要避免這種狀況發生,就要在資源宣告時配合defer
去做資源清除。
func main() {
f, err := os.Open("/tmp/dat")
if err != nil {
fmt.Println(err)
return
}
defer func() { // 延遲執行,而且函式 return 前一定會執行
if f != nil {
f.Close()
}
}()
a, err := f.Read(b1)
// .
// 正常執行
// .
}
這種方式就能確保遇到非預期的錯誤時,資源也能正常關閉
Go語言沒有拋出例外的機制,如果在執行過程需要中斷目前的流程,就可以使用這種機制。panic
會使程式中斷,而且會一路中斷回根節點。
panic
時會先執行defer
內的東西,執行完後才會繼續回傳panic
,並退出程式,因此可以利用這個機制做錯誤處理。
func main() {
outside()
fmt.Println("function main")
}
func outside() {
func() {
fmt.Println("function inside")
// panic("test")
}()
fmt.Println("function outside")
}
正常執行
output:
function inside
function outside
function main
若將註解去掉,測試panic的話
output:
function inside
發生例外狀況: panic
"test"
.
.
可以看到panic
會一路斷回main
recover
是一個函數,可以捕捉panic
輸入的值,並且讓程序繼續運行,若成功攔截panic
,則函式不會中斷回根結點,就能繼續執行了。
在defer
內使用recover
攔截panic
,做完處理後程式就能繼續執行了。
package main
import "fmt"
func panicFunc() {
fmt.Println("panic function")
panic("panic")
}
func normalFunc() {
fmt.Println("normal function")
}
func throwsPanic(fn func()) {
defer func() {
x := recover()
if x != nil {
fmt.Println("recover happended")
}
}()
fn()
}
func main() {
throwsPanic(panicFunc)
throwsPanic(normalFunc)
fmt.Println("Finish main.")
}
output:
panic function
recover happended
normal function
Finish main.
耶耶,今天的算比較輕鬆的內容,大部分Go方法也都有實做出error的部分,所以要使用哪種方法做錯誤處理主要是看個人習慣或團隊習慣,今天就介紹到這邊吧owo
[Golang] 相當好用但又要注意的defer
https://www.evanlin.com/golang-know-using-defer/
GOLANG - 異常處理 - PANIC 與 RECOVER
https://hoohoo.top/blog/golang-exception-handling-panic-and-recover/
defer、panic、recover
https://openhome.cc/Gossip/Go/DeferPanicRecover.html
Go延迟(defer)实例
https://www.yiibai.com/go/golang-defer.html
Go的error與panic
https://www.ithome.com.tw/voice/103455