iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 4
1
自我挑戰組

Let's Eat GO ! 實務開發雜談by Golang系列 第 4

Day4 .[重災經驗篇] 常見的panic造成原因

許多panic產生的原因是由於程式沒寫好造成的

下面談談幾個常見的陷阱

  • slice index
  • map 未先初始化
  • error 的Error()不一定可以使用
  • nil pointer
  • defer

slice index

Golang的array和slice有別,slice無法確定內容元素的數量。

用index的方式(限定數字)去取得slice的指定元素是可以,不過千萬要小心,擁有元素的數量小於指定的index,就會發生錯誤。

程式碼示意

go playground


建議辦法

若要用此用法,最好先判斷slice長度,可保平安。

if len(peopleLine) >= 11 {
    b := peopleLine[10]
    fmt.Println("b is:", b)	
}

map 未先初始化

Map 型態的變數可以先用var宣告出來,也可以指定index進行賦值,編譯時也不會報錯。但是未先用make或其他方式宣告記憶體,執行程式下去會立刻炸出panic送你。

程式碼示意

go playground

建議辦法

使用map,記得事先用make建立。

	gaintMap := make(meowMap, 0)
	gaintMap["a"] = "aa"

error 的Error()不一定可以使用

有次為了紀錄程式log,貪圖方便,竟妄想一行把錯誤資訊串在字串方便記錄,結果疏忽了,錯誤資訊也要發生錯誤才會有,從nil去取得Error()的內容,無疑的程式不丟panic給你才怪。

程式碼示意

go playground

建議辦法

注意.Error 只在判斷有err發生的範圍使用

	if err != nil {
		err.Error()
	}

nil pointer

nil pointer 的錯誤也很常發生,其實上面提到的三個常見錯誤,廣義上他們也是屬於某種nil pointer。

常見的情形,是發生在當你取得method返回值型態,不是單純的int、string、float64這種,而是比較複雜的slice、map、或者struct、interface甚至function,可能就要特別留意。

如果發生問題,回傳值很可能是拿到預設值而已,試想一下,slice、map的預設值是什麼?這篇文章提到slice和map可能發生的panic是什麼情形造成的,各位看倌就可想而知了。

若回傳的型態是struct、interface、function,發生問題時可能這整個東西都是nil(預設值唄),或者內容是預設值(指struct),nil當然就不能呼叫你想使用的函式,就如前一點的錯誤情形類似,一但使用就死定了。

我認為這件事情,是當你在撰寫method是否會有error回傳的時候,就需要停下來稍微思考和決定,當真的有錯誤發生和回傳的時候,接下的程式該怎麼去做,在Golang寫了一段時間後,可能潛移默化地且自然而然,四處想到使用error作為處理上的判斷,但也請將思考接到錯誤的後續處理,也練成自然而然有仔細考慮的習慣。


defer

這個追根究底也是nil pointer的問題,而且造成原因與上面所述沒什麼兩樣,有些人喜歡用defer的方式,在發生錯誤或者某些判斷,離開所在的function時執行某些動作,然後要呼叫函式執行某些動作,前提是你也要先有實體才行,沒有實體先出來,或因為發生錯誤導致沒有實體化,執行到這段也是只有發生panic的命。

如下面示意,你確定離開function時,這個connector並非是nil嗎?或者Close()是有實體的嗎?

	defer connector.Close()

下篇談談不同gotuine對map的操作,這可就是fatal error了,而不是panic可以復原......


上一篇
Day3 .[重災經驗篇] 關於panic的處理
下一篇
Day5 .[重災經驗篇] gorutine與map的讀寫
系列文
Let's Eat GO ! 實務開發雜談by Golang30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言