2 回答

TA貢獻(xiàn)1803條經(jīng)驗(yàn) 獲得超6個(gè)贊
為了詳細(xì)說(shuō)明 FUZxxl 的解釋,go 區(qū)分了錯(cuò)誤(可能出錯(cuò)的事情確實(shí)出錯(cuò)了)和異常(不可能出錯(cuò)的事情實(shí)際上出錯(cuò)了)。
區(qū)別有時(shí)可能很微妙(因?yàn)樗蕾囉凇耙馔狻保?,但它也可能比您在其他語(yǔ)言中看到的“一切都是例外”更清晰。
例如,考慮可能溢出的整數(shù)。一種可能性是將其視為“正?!毙袨?,應(yīng)適當(dāng)處理:
func safe_add(x, y uint32) (uint32, error) {
z := x + y
if z < x || z < y {
return 0, fmt.Errorf("Integer overflow")
}
return z, nil
}
另一個(gè)是考慮它“永遠(yuǎn)不會(huì)發(fā)生”,并panic在萬(wàn)一發(fā)生時(shí)在不太可能的情況下運(yùn)行運(yùn)行時(shí):
func panic_add(x, y uint32) uint32 {
z, err := safe_add(x, y)
if err != nil {
panic(err)
}
return z
}
(請(qǐng)注意,我在這里使用了我自己的“safe_add”,但您當(dāng)然不必這樣做)
主要區(qū)別在于您之后處理錯(cuò)誤的方式。添加一個(gè)數(shù)字到它自己直到它溢出errors 給出:
func safeloop(u uint32) {
var err error
for {
if u, err = safe_add(u, u); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u)
}
}
}
處理恐慌時(shí)使用recover內(nèi)置函數(shù):
func panicloop(u uint32) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
for {
u = panic_add(u, u)
fmt.Println(u)
}
}
(操場(chǎng)上的完整示例)
請(qǐng)注意,恐慌版本有一個(gè)更簡(jiǎn)單的循環(huán),因?yàn)槟旧蠌牟黄谕魏五e(cuò)誤并且從不檢查錯(cuò)誤。與此相反的是,處理恐慌的方法非常麻煩,即使是這樣一個(gè)非常簡(jiǎn)單的例子。您defer是一個(gè)函數(shù),它會(huì)recover在錯(cuò)誤出現(xiàn)并脫離函數(shù)時(shí)調(diào)用并捕獲錯(cuò)誤。當(dāng)你的代碼變得更復(fù)雜,跟蹤確切位置/恐慌是如何產(chǎn)生并作用于它因此可以成為很多比他們可能出現(xiàn)的地方檢查錯(cuò)誤,與更復(fù)雜result, err := func_which_may_fail(...)的圖案。
您甚至可以在恐慌之間交替,恢復(fù)哪些返回錯(cuò)誤,將錯(cuò)誤轉(zhuǎn)換為恐慌,......但這(可以理解)被認(rèn)為是糟糕的設(shè)計(jì)。
go 博客上有一些關(guān)于錯(cuò)誤處理和恐慌的好資源。該規(guī)范是讀的好。
在您的情況下,由于您期望“服務(wù)器已關(guān)閉”是一種非常頻繁的行為,因此您絕對(duì)應(yīng)該error按照 FUZxxl 的建議行事,但我希望這可能對(duì)您(或其他人)了解錯(cuò)誤處理的工作原理有用在去。
- 2 回答
- 0 關(guān)注
- 246 瀏覽
添加回答
舉報(bào)