Go 中如何準(zhǔn)確地判斷和識(shí)別各種網(wǎng)絡(luò)錯(cuò)誤
Go語(yǔ)言集成了簡(jiǎn)單易用的網(wǎng)路庫(kù),今天的推送是一線架構(gòu)師分享的Go網(wǎng)絡(luò)庫(kù)使用入門(mén)指南。
Go 自帶的網(wǎng)絡(luò)標(biāo)準(zhǔn)庫(kù)可能讓很多第一次使用它的人感慨,這個(gè)庫(kù)讓網(wǎng)絡(luò)編程的門(mén)檻低到了令人發(fā)指的地步。然而,封裝層次與開(kāi)發(fā)人員的可控性往往是矛盾的。Go 的網(wǎng)絡(luò)庫(kù)封裝程度算是一個(gè)不錯(cuò)的折衷,絕大部分時(shí)候,我們只需要調(diào)用 Dial, Read, Write Close 幾個(gè)基本操作就可以了。
但是,網(wǎng)絡(luò)是復(fù)雜的。我們有時(shí)候需要細(xì)致的處理網(wǎng)絡(luò)中的各種錯(cuò)誤,根據(jù)不同的錯(cuò)誤進(jìn)行不同的處理。比如我們遇到一個(gè)網(wǎng)絡(luò)錯(cuò)誤時(shí),需要區(qū)分這個(gè)錯(cuò)誤是因?yàn)闊o(wú)法解析 host ip, 還是 TCP 無(wú)法建立連接,亦或是讀寫(xiě)超時(shí)。一開(kāi)始的時(shí)候,我們的寫(xiě)法可能是這樣的:

這種根據(jù)錯(cuò)誤信息進(jìn)行字符串匹配進(jìn)行判斷的方法有非常明顯的局限性:該錯(cuò)誤信息依賴(lài)于操作系統(tǒng),不同的操作系統(tǒng)對(duì)于同一錯(cuò)誤返回的字符串信息可能是不同的。因此,這種判斷網(wǎng)絡(luò)錯(cuò)誤類(lèi)型的方法是不可靠的。那么有沒(méi)有一種準(zhǔn)確而可靠的判斷各種網(wǎng)絡(luò)錯(cuò)誤的方式呢?答案是肯定的。
我們知道在 Go 中,error 是一個(gè)內(nèi)建的 interface 類(lèi)型:

要準(zhǔn)確判斷不同的錯(cuò)誤類(lèi)型,我們只需要類(lèi)型斷言出其錯(cuò)誤類(lèi)型即可。
在 Go 的網(wǎng)絡(luò)標(biāo)準(zhǔn)庫(kù)中,錯(cuò)誤類(lèi)型被統(tǒng)一封裝為 net.Error 的 interface 類(lèi)型:

而 net.Error 類(lèi)型的具體 concrete 類(lèi)型又被封裝為 net.OpError 類(lèi)型:

其中,net.OpError.Err 可能是以下幾種類(lèi)型:
-
net.DNSError -
net.InvalidAddrError -
net.UnknownNetworkError -
net.AddrError -
net.DNSConfigError -
*os.SyscallError
*os.SyscallError 錯(cuò)誤比較特殊,與具體操作系統(tǒng)調(diào)用有關(guān):

對(duì)于我們關(guān)心的網(wǎng)絡(luò)錯(cuò)誤,SyscallError.Err 一般為 sys.Errno 類(lèi)型,與網(wǎng)絡(luò)錯(cuò)誤相關(guān)的常用值有:
-
syscall.ECONNREFUSED -
syscall.ETIMEDOUT
看到這里,你可能忍不住要吐槽 Go 這種錯(cuò)誤嵌套處理了,事實(shí)上,官方也意識(shí)到了這種錯(cuò)誤處理的問(wèn)題,在 Go 2中,可能會(huì)出現(xiàn)新的錯(cuò)誤和異常處理方式,可以參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(píng): RETHINKING ERRORS FOR GO 2 (https://liudanking.com/arch/gopherchina-2018-keynote-%E7%82%B9%E8%AF%84/).
當(dāng)前階段,我們依然要直面這種錯(cuò)誤處理方式。為了方便大家理解 Go 網(wǎng)絡(luò)標(biāo)準(zhǔn)庫(kù)中處理錯(cuò)誤的方式,我們把上面的錯(cuò)誤嵌套整理了一張關(guān)系圖:
明白了網(wǎng)絡(luò)標(biāo)準(zhǔn)庫(kù)中處理錯(cuò)誤的邏輯,判斷和識(shí)別各種類(lèi)型的網(wǎng)絡(luò)錯(cuò)誤就非常簡(jiǎn)單了:對(duì)網(wǎng)絡(luò)錯(cuò)誤進(jìn)行類(lèi)型斷言。以我們團(tuán)隊(duì)主要關(guān)心的 DNS 解析錯(cuò)誤、TCP 無(wú)法建立連接、讀寫(xiě)超時(shí)為例,判斷邏輯可以是這樣:

這種錯(cuò)誤判定方式除了能解決最開(kāi)始提到的可靠性和準(zhǔn)確性問(wèn)題,也具有良好的普適性。即基于 net 的其他標(biāo)準(zhǔn)庫(kù),如 net/http 也支持這種錯(cuò)誤判斷方式。
轉(zhuǎn)自:
liudanking.com/network/go-%e4%b8%ad%e5%a6%82%e4%bd%95%e5%87%86%e7%a1%ae%e5%9c%b0%e5%88%a4%e6%96%ad%e5%92%8c%e8%af%86%e5%88%ab%e5%90%84%e7%a7%8d%e7%bd%91%e7%bb%9c%e9%94%99%e8%af%af/