Go語言中的運行時的錯誤error

關(guān)鍵點

希望通過下面的關(guān)鍵詞,能夠?qū)崿F(xiàn)目的:能夠快速回憶十绑,理解聚至,復(fù)習 知識點:

1、Go語言中本橙,運行時錯誤處理扳躬;

  • 沒有類似于Java中的異常處理機制

  • Go語言中,是將錯誤,作為函數(shù)的正常值贷币,進行返回

  • Java中的異常击胜,開發(fā)者可以捕獲后,不處理役纹,但是偶摔,Go語言中,是作為正常業(yè)務(wù)邏輯中的情況促脉,這是從思想上的不一樣的

2辰斋、Go語言的錯誤處理思想設(shè)計包含以下特征:
A、一個可能造成錯誤的函數(shù)瘸味,需要返回值中返回一個錯誤接口(error)宫仗,

  • 如果調(diào)用是成功的,錯誤接口將返回 nil旁仿,

  • 否則返回錯誤藕夫。

B、在函數(shù)調(diào)用后需要檢查錯誤枯冈,如果發(fā)生錯誤毅贮,則進行必要的錯誤處理。

3霜幼、Go語言Java異常處理 有什么不同么嫩码?

  • Go語言沒有類似 Java 或 .NET 中的異常處理機制誉尖,

  • 可以使用 defer罪既、panicrecover模擬铡恕,但官方并不主張這樣做琢感,

  • 其他語言的異常機制已被過度使用,上層邏輯需要為函數(shù)發(fā)生的異常付出太多的資源探熔,

  • 同時驹针,如果函數(shù)使用者覺得錯誤處理很麻煩而忽略錯誤,那么程序?qū)⒃?code>不可預(yù)知的時刻崩潰诀艰。

  • Go語言希望開發(fā)者將錯誤處理視為正常開發(fā)必須實現(xiàn)的環(huán)節(jié)柬甥,正確地處理每一個可能發(fā)生錯誤的函數(shù)

  • Go語言使用返回值返回錯誤的機制其垄,也能大幅降低編譯器苛蒲、運行時處理錯誤復(fù)雜度,讓開發(fā)者真正地掌握錯誤的處理绿满。

1臂外、net 包中的例子

net.Dial() 是Go語言系統(tǒng)包 net 即中的一個函數(shù),一般用于創(chuàng)建一個 Socket 連接。

net.Dial 擁有兩個返回值漏健,即 Conn 和 error嚎货,這個函數(shù)是阻塞的,因此在 Socket 操作后蔫浆,會返回 Conn 連接對象和 error殖属,如果發(fā)生錯誤,error 會告知錯誤的類型瓦盛,Conn 會返回空忱辅。

根據(jù)Go語言的錯誤處理機制,Conn 是其重要的返回值谭溉,因此墙懂,為這個函數(shù)增加一個錯誤返回,類似為 error扮念,參見下面的代碼:

func Dial(network, address string) (Conn, error) {
    var d Dialer
    return d.Dial(network, address)
}
在 io 包中的 Writer 接口也擁有錯誤返回损搬,代碼如下:
type Writer interface {
    Write(p []byte) (n int, err error)
}
io 包中還有 Closer 接口,只有一個錯誤返回柜与,代碼如下:
type Closer interface {
    Close() error
}

2巧勤、錯誤接口的定義格式

error 是 Go 系統(tǒng)聲明的接口類型,代碼如下:

type error interface {
    Error() string
}

所有符合 Error()string 格式的方法弄匕,都能實現(xiàn)錯誤接口颅悉,Error() 方法返回錯誤的具體描述,使用者可以通過這個字符串知道發(fā)生了什么錯誤迁匠。
自定義一個錯誤

返回錯誤前剩瓶,需要定義會產(chǎn)生哪些可能的錯誤,在Go語言中城丧,使用 errors 包進行錯誤的定義延曙,格式如下:

var err = errors.New("this is an error")

錯誤字符串由于相對固定,一般在包作用域聲明亡哄,應(yīng)盡量減少在使用時直接使用 errors.New 返回枝缔。

1) errors 包

Go語言的 errors 中對 New 的定義非常簡單,代碼如下:

// 創(chuàng)建錯誤對象
func New(text string) error {
    return &errorString{text}
}
// 錯誤字符串
type errorString struct {
    s string
}
// 返回發(fā)生何種錯誤
func (e *errorString) Error() string {
    return e.s
}

代碼說明如下:

  • 第 2 行蚊惯,將 errorString 結(jié)構(gòu)體實例化愿卸,并賦值錯誤描述的成員。
  • 第 7 行截型,聲明 errorString 結(jié)構(gòu)體趴荸,擁有一個成員,描述錯誤內(nèi)容菠劝。
  • 第 12 行赊舶,實現(xiàn) error 接口的 Error() 方法睁搭,該方法返回成員中的錯誤描述。

2) 在代碼中使用錯誤定義

下面的代碼會定義一個除法函數(shù)笼平,當除數(shù)為 0 時园骆,返回一個預(yù)定義的除數(shù)為 0 的錯誤。

package main
import (
    "errors"
    "fmt"
)
// 定義除數(shù)為0的錯誤
var errDivisionByZero = errors.New("division by zero")
func div(dividend, divisor int) (int, error) {
    // 判斷除數(shù)為0的情況并返回
    if divisor == 0 {
        return 0, errDivisionByZero
    }
    // 正常計算寓调,返回空錯誤
    return dividend / divisor, nil
}
func main() {
    fmt.Println(div(1, 0))
}

代碼輸出如下:

0 division by zero

代碼說明:

  • 第 9 行锌唾,預(yù)定義除數(shù)為 0 的錯誤。
  • 第 11 行夺英,聲明除法函數(shù)晌涕,輸入被除數(shù)和除數(shù),返回商和錯誤痛悯。
  • 第 14 行余黎,在除法計算中,如果除數(shù)為 0载萌,計算結(jié)果為無窮大惧财,為了避免這種情況,對除數(shù)進行判斷扭仁,并返回商為 0 和除數(shù)為 0 的錯誤對象垮衷。
  • 第 19 行,進行正常的除法計算乖坠,沒有發(fā)生錯誤時搀突,錯誤對象返回 nil。

3熊泵、示例:在解析中使用自定義錯誤

使用 errors.New 定義的錯誤字符串的錯誤類型是無法提供豐富的錯誤信息的仰迁,那么,如果需要攜帶錯誤信息返回戈次,就需要借助自定義結(jié)構(gòu)體實現(xiàn)錯誤接口轩勘。

下面代碼將實現(xiàn)一個解析錯誤(ParseError)筒扒,這種錯誤包含兩個內(nèi)容怯邪,分別是文件名和行號,解析錯誤的結(jié)構(gòu)還實現(xiàn)了 error 接口的 Error() 方法花墩,返回錯誤描述時悬秉,就需要將文件名和行號返回。

package main
import (
    "fmt"
)
// 聲明一個解析錯誤
type ParseError struct {
    Filename string // 文件名
    Line     int    // 行號
}
// 實現(xiàn)error接口冰蘑,返回錯誤描述
func (e *ParseError) Error() string {
    return fmt.Sprintf("%s:%d", e.Filename, e.Line)
}
// 創(chuàng)建一些解析錯誤
func newParseError(filename string, line int) error {
    return &ParseError{filename, line}
}
func main() {
    var e error
    // 創(chuàng)建一個錯誤實例和泌,包含文件名和行號
    e = newParseError("main.go", 1)
    // 通過error接口查看錯誤描述
    fmt.Println(e.Error())
    // 根據(jù)錯誤接口具體的類型,獲取詳細錯誤信息
    switch detail := e.(type) {
    case *ParseError: // 這是一個解析錯誤
        fmt.Printf("Filename: %s Line: %d\n", detail.Filename, detail.Line)
    default: // 其他類型的錯誤
        fmt.Println("other error")
    }
}

代碼輸出如下:

main.go:1
Filename: main.go Line: 1

代碼說明如下:

  • 第 8 行祠肥,聲明了一個解析錯誤的結(jié)構(gòu)體武氓,解析錯誤包含有 2 個成員,分別是文件名和行號。
  • 第 14 行县恕,實現(xiàn)了錯誤接口东羹,將成員的文件名和行號格式化為字符串返回。
  • 第 19 行忠烛,根據(jù)給定的文件名和行號創(chuàng)建一個錯誤實例属提。
  • 第 25 行,聲明一個錯誤接口類型美尸。
  • 第 27 行冤议,創(chuàng)建一個實例,這個錯誤接口內(nèi)部是 *ParserError 類型师坎,攜帶有文件名 main.go 和行號 1恕酸。
  • 第 30 行,調(diào)用 Error() 方法胯陋,通過第 15 行返回錯誤的詳細信息尸疆。
  • 第 33 行,通過錯誤斷言惶岭,取出發(fā)生錯誤的詳細類型寿弱。
  • 第 34 行,通過分析這個錯誤的類型按灶,得知錯誤類型為 *ParserError症革,此時可以獲取到詳細的錯誤信息。
  • 第 36 行鸯旁,如果不是我們能夠處理的錯誤類型噪矛,會打印出其他錯誤做出其他的處理。

錯誤對象都要實現(xiàn) error 接口的 Error() 方法铺罢,這樣艇挨,所有的錯誤都可以獲得字符串的描述,如果想進一步知道錯誤的詳細信息韭赘,可以通過類型斷言缩滨,將錯誤對象轉(zhuǎn)為具體的錯誤類型進行錯誤詳細信息的獲取。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泉瞻,一起剝皮案震驚了整個濱河市脉漏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袖牙,老刑警劉巖侧巨,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鞭达,居然都是意外死亡司忱,警方通過查閱死者的電腦和手機皇忿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坦仍,“玉大人禁添,你說我怎么就攤上這事〗白伲” “怎么了老翘?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锻离。 經(jīng)常有香客問我铺峭,道長,這世上最難降的妖魔是什么汽纠? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任卫键,我火速辦了婚禮,結(jié)果婚禮上虱朵,老公的妹妹穿的比我還像新娘莉炉。我一直安慰自己,他們只是感情好碴犬,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布絮宁。 她就那樣靜靜地躺著,像睡著了一般服协。 火紅的嫁衣襯著肌膚如雪绍昂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天偿荷,我揣著相機與錄音窘游,去河邊找鬼。 笑死跳纳,一個胖子當著我的面吹牛忍饰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寺庄,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼艾蓝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铣揉?” 一聲冷哼從身側(cè)響起饶深,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤轴捎,失蹤者是張志新(化名)和其女友劉穎情屹,沒想到半個月后诗良,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡朽合,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年俱两,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曹步。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡宪彩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讲婚,到底是詐尸還是另有隱情尿孔,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布筹麸,位于F島的核電站活合,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏物赶。R本人自食惡果不足惜白指,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酵紫。 院中可真熱鬧告嘲,春花似錦、人聲如沸奖地。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽参歹。三九已至轧坎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泽示,已是汗流浹背缸血。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留械筛,地道東北人捎泻。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像埋哟,于是被迫代替她去往敵國和親笆豁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容