我寫到現在,我一直覺得 golang 的 error 設計,一直讓人又愛又恨…,我們今天會分兩個面向來介紹它,一種是語言層面的 error ,也就是 panic,一種就是一般調用 func 所回傳的 error,改怎麼做整理…

panic

語言層級的 panic 常常發生在,concurrency 時沒控制好資源,大致上有以下幾種情況

  1. deadlock 不同 thread 間互相卡死
  2. data race 沒有做好 lock ,造成資源競爭
  3. nil of pointer 存取到空的 pointer

上述的三種錯誤都會直接讓 golang 直噴 panic,我自己帶我們家的 junior 時,都會交代一句話

他強任他強、清風拂山崗;他橫任他橫、明月照大江

他自狠來他自惡,我自一口真氣足

上面的話語引述自金庸的『倚天屠龍記』的『九陽真經』要領,意思就是,不管外界再怎麼狠毒,自身都不應該受到影響。我們寫 server 的人,可以因為 request 太多,暫時 pending 住,少收一些 request 但不能因為這樣整個 server 死掉。

下面為攔截 panic 錯誤的方式

package main

import (
	"fmt"
)

func Excute() {
	panic("wtf...")
}
func main() {

	//defer 在這邊並沒有另外立章節介紹,在這邊簡單說明,他就是用在,這個func 結束前,你最後需要做什麼
	//ex 有些o pen file的行為 最後需要 close 等等
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()
	Excute()

	fmt.Println("end")
}

https://play.golang.org/p/82pg_A1epbe

error

前面就有講到 golang error 機制設計,我個人很喜歡,但也有一派人馬認為它會讓 code 看起來很瑣碎,因為它少掉了巢狀式 try catch ,這樣的好處在閱讀 source code,難易度大簡,但是換來的卻是

if err != nil {
    return
}

寫到這裡,如果有稍微觀摩過一些 github 上的 golang pcakge,或是閱讀 golang source code,應該都不陌生上面這段 code。

之前去上海的 GopherChina2018 裡面有 golang 開發團隊的成員說,預計在 2.0 時,golang error handler 會有一個不小的修正。

在這邊要特別宣導一下,只要有看到 func 的回傳值有 error ,請一定要接出來,不要忽略它。以官方 net.Listen 套件為例

ln, err := net.Listen("tcp", ":8080")
if err != nil {
    error handler ...
}
conn, err := ln.Accept()

如上,如果沒有讓它直接攔到,讓它持續往下執行,做了 ln.Accept(),這時侯 ln 是 nil ,所以會觸發 nil of pointer,所以請大家不要嫌麻煩,任何錯誤都要接起來並且處理,可以省掉很多 debug 時間。