新聞中心
Go語言的錯(cuò)誤處理思想及設(shè)計(jì)包含以下特征:

成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括畢節(jié)網(wǎng)站建設(shè)、畢節(jié)網(wǎng)站制作、畢節(jié)網(wǎng)頁(yè)制作以及畢節(jié)網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,畢節(jié)網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到畢節(jié)省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
- 一個(gè)可能造成錯(cuò)誤的函數(shù),需要返回值中返回一個(gè)錯(cuò)誤接口(error),如果調(diào)用是成功的,錯(cuò)誤接口將返回 nil,否則返回錯(cuò)誤。
- 在函數(shù)調(diào)用后需要檢查錯(cuò)誤,如果發(fā)生錯(cuò)誤,則進(jìn)行必要的錯(cuò)誤處理。
Go語言沒有類似 Java 或 .NET 中的異常處理機(jī)制,雖然可以使用 defer、panic、recover 模擬,但官方并不主張這樣做,Go語言的設(shè)計(jì)者認(rèn)為其他語言的異常機(jī)制已被過度使用,上層邏輯需要為函數(shù)發(fā)生的異常付出太多的資源,同時(shí),如果函數(shù)使用者覺得錯(cuò)誤處理很麻煩而忽略錯(cuò)誤,那么程序?qū)⒃诓豢深A(yù)知的時(shí)刻崩潰。
Go語言希望開發(fā)者將錯(cuò)誤處理視為正常開發(fā)必須實(shí)現(xiàn)的環(huán)節(jié),正確地處理每一個(gè)可能發(fā)生錯(cuò)誤的函數(shù),同時(shí),Go語言使用返回值返回錯(cuò)誤的機(jī)制,也能大幅降低編譯器、運(yùn)行時(shí)處理錯(cuò)誤的復(fù)雜度,讓開發(fā)者真正地掌握錯(cuò)誤的處理。
net 包中的例子
net.Dial() 是Go語言系統(tǒng)包 net 即中的一個(gè)函數(shù),一般用于創(chuàng)建一個(gè) Socket 連接。
net.Dial 擁有兩個(gè)返回值,即 Conn 和 error,這個(gè)函數(shù)是阻塞的,因此在 Socket 操作后,會(huì)返回 Conn 連接對(duì)象和 error,如果發(fā)生錯(cuò)誤,error 會(huì)告知錯(cuò)誤的類型,Conn 會(huì)返回空。
根據(jù)Go語言的錯(cuò)誤處理機(jī)制,Conn 是其重要的返回值,因此,為這個(gè)函數(shù)增加一個(gè)錯(cuò)誤返回,類似為 error,參見下面的代碼:
func Dial(network, address string) (Conn, error) {
var d Dialer
return d.Dial(network, address)
}在 io 包中的 Writer 接口也擁有錯(cuò)誤返回,代碼如下:
type Writer interface {
Write(p []byte) (n int, err error)
}io 包中還有 Closer 接口,只有一個(gè)錯(cuò)誤返回,代碼如下:
type Closer interface {
Close() error
}錯(cuò)誤接口的定義格式
error 是 Go 系統(tǒng)聲明的接口類型,代碼如下:
type error interface {
Error() string
}所有符合 Error()string 格式的方法,都能實(shí)現(xiàn)錯(cuò)誤接口,Error() 方法返回錯(cuò)誤的具體描述,使用者可以通過這個(gè)字符串知道發(fā)生了什么錯(cuò)誤。
自定義一個(gè)錯(cuò)誤
返回錯(cuò)誤前,需要定義會(huì)產(chǎn)生哪些可能的錯(cuò)誤,在Go語言中,使用 errors 包進(jìn)行錯(cuò)誤的定義,格式如下:
var err = errors.New("this is an error")錯(cuò)誤字符串由于相對(duì)固定,一般在包作用域聲明,應(yīng)盡量減少在使用時(shí)直接使用 errors.New 返回。
1) errors 包
Go語言的 errors 中對(duì) New 的定義非常簡(jiǎn)單,代碼如下:
// 創(chuàng)建錯(cuò)誤對(duì)象
func New(text string) error {
return &errorString{text}
}
// 錯(cuò)誤字符串
type errorString struct {
s string
}
// 返回發(fā)生何種錯(cuò)誤
func (e *errorString) Error() string {
return e.s
}代碼說明如下:
- 第 2 行,將 errorString 結(jié)構(gòu)體實(shí)例化,并賦值錯(cuò)誤描述的成員。
- 第 7 行,聲明 errorString 結(jié)構(gòu)體,擁有一個(gè)成員,描述錯(cuò)誤內(nèi)容。
- 第 12 行,實(shí)現(xiàn) error 接口的 Error() 方法,該方法返回成員中的錯(cuò)誤描述。
2) 在代碼中使用錯(cuò)誤定義
下面的代碼會(huì)定義一個(gè)除法函數(shù),當(dāng)除數(shù)為 0 時(shí),返回一個(gè)預(yù)定義的除數(shù)為 0 的錯(cuò)誤。
package main
import (
"errors"
"fmt"
)
// 定義除數(shù)為0的錯(cuò)誤
var errDivisionByZero = errors.New("division by zero")
func div(dividend, divisor int) (int, error) {
// 判斷除數(shù)為0的情況并返回
if divisor == 0 {
return 0, errDivisionByZero
}
// 正常計(jì)算,返回空錯(cuò)誤
return dividend / divisor, nil
}
func main() {
fmt.Println(div(1, 0))
}代碼輸出如下:
0 division by zero
代碼說明:
- 第 9 行,預(yù)定義除數(shù)為 0 的錯(cuò)誤。
- 第 11 行,聲明除法函數(shù),輸入被除數(shù)和除數(shù),返回商和錯(cuò)誤。
- 第 14 行,在除法計(jì)算中,如果除數(shù)為 0,計(jì)算結(jié)果為無窮大,為了避免這種情況,對(duì)除數(shù)進(jìn)行判斷,并返回商為 0 和除數(shù)為 0 的錯(cuò)誤對(duì)象。
- 第 19 行,進(jìn)行正常的除法計(jì)算,沒有發(fā)生錯(cuò)誤時(shí),錯(cuò)誤對(duì)象返回 nil。
示例:在解析中使用自定義錯(cuò)誤
使用 errors.New 定義的錯(cuò)誤字符串的錯(cuò)誤類型是無法提供豐富的錯(cuò)誤信息的,那么,如果需要攜帶錯(cuò)誤信息返回,就需要借助自定義結(jié)構(gòu)體實(shí)現(xiàn)錯(cuò)誤接口。
下面代碼將實(shí)現(xiàn)一個(gè)解析錯(cuò)誤(ParseError),這種錯(cuò)誤包含兩個(gè)內(nèi)容,分別是文件名和行號(hào),解析錯(cuò)誤的結(jié)構(gòu)還實(shí)現(xiàn)了 error 接口的 Error() 方法,返回錯(cuò)誤描述時(shí),就需要將文件名和行號(hào)返回。
package main
import (
"fmt"
)
// 聲明一個(gè)解析錯(cuò)誤
type ParseError struct {
Filename string // 文件名
Line int // 行號(hào)
}
// 實(shí)現(xiàn)error接口,返回錯(cuò)誤描述
func (e *ParseError) Error() string {
return fmt.Sprintf("%s:%d", e.Filename, e.Line)
}
// 創(chuàng)建一些解析錯(cuò)誤
func newParseError(filename string, line int) error {
return &ParseError{filename, line}
}
func main() {
var e error
// 創(chuàng)建一個(gè)錯(cuò)誤實(shí)例,包含文件名和行號(hào)
e = newParseError("main.go", 1)
// 通過error接口查看錯(cuò)誤描述
fmt.Println(e.Error())
// 根據(jù)錯(cuò)誤接口具體的類型,獲取詳細(xì)錯(cuò)誤信息
switch detail := e.(type) {
case *ParseError: // 這是一個(gè)解析錯(cuò)誤
fmt.Printf("Filename: %s Line: %d\n", detail.Filename, detail.Line)
default: // 其他類型的錯(cuò)誤
fmt.Println("other error")
}
}代碼輸出如下:
main.go:1
Filename: main.go Line: 1
代碼說明如下:
- 第 8 行,聲明了一個(gè)解析錯(cuò)誤的結(jié)構(gòu)體,解析錯(cuò)誤包含有 2 個(gè)成員,分別是文件名和行號(hào)。
- 第 14 行,實(shí)現(xiàn)了錯(cuò)誤接口,將成員的文件名和行號(hào)格式化為字符串返回。
- 第 19 行,根據(jù)給定的文件名和行號(hào)創(chuàng)建一個(gè)錯(cuò)誤實(shí)例。
- 第 25 行,聲明一個(gè)錯(cuò)誤接口類型。
- 第 27 行,創(chuàng)建一個(gè)實(shí)例,這個(gè)錯(cuò)誤接口內(nèi)部是 *ParserError 類型,攜帶有文件名 main.go 和行號(hào) 1。
- 第 30 行,調(diào)用 Error() 方法,通過第 15 行返回錯(cuò)誤的詳細(xì)信息。
- 第 33 行,通過錯(cuò)誤斷言,取出發(fā)生錯(cuò)誤的詳細(xì)類型。
- 第 34 行,通過分析這個(gè)錯(cuò)誤的類型,得知錯(cuò)誤類型為 *ParserError,此時(shí)可以獲取到詳細(xì)的錯(cuò)誤信息。
- 第 36 行,如果不是我們能夠處理的錯(cuò)誤類型,會(huì)打印出其他錯(cuò)誤做出其他的處理。
錯(cuò)誤對(duì)象都要實(shí)現(xiàn) error 接口的 Error() 方法,這樣,所有的錯(cuò)誤都可以獲得字符串的描述,如果想進(jìn)一步知道錯(cuò)誤的詳細(xì)信息,可以通過類型斷言,將錯(cuò)誤對(duì)象轉(zhuǎn)為具體的錯(cuò)誤類型進(jìn)行錯(cuò)誤詳細(xì)信息的獲取。
網(wǎng)站名稱:創(chuàng)新互聯(lián)GO教程:Go語言處理運(yùn)行時(shí)錯(cuò)誤
當(dāng)前網(wǎng)址:http://m.5511xx.com/article/cosshei.html


咨詢
建站咨詢
