掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Go語言的錯誤處理思想及設(shè)計包含以下特征:

成都創(chuàng)新互聯(lián)公司服務(wù)項目包括畢節(jié)網(wǎng)站建設(shè)、畢節(jié)網(wǎng)站制作、畢節(jié)網(wǎng)頁制作以及畢節(jié)網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,畢節(jié)網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到畢節(jié)省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
Go語言沒有類似 Java 或 .NET 中的異常處理機制,雖然可以使用 defer、panic、recover 模擬,但官方并不主張這樣做,Go語言的設(shè)計者認(rèn)為其他語言的異常機制已被過度使用,上層邏輯需要為函數(shù)發(fā)生的異常付出太多的資源,同時,如果函數(shù)使用者覺得錯誤處理很麻煩而忽略錯誤,那么程序?qū)⒃诓豢深A(yù)知的時刻崩潰。
Go語言希望開發(fā)者將錯誤處理視為正常開發(fā)必須實現(xiàn)的環(huán)節(jié),正確地處理每一個可能發(fā)生錯誤的函數(shù),同時,Go語言使用返回值返回錯誤的機制,也能大幅降低編譯器、運行時處理錯誤的復(fù)雜度,讓開發(fā)者真正地掌握錯誤的處理。
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
}error 是 Go 系統(tǒng)聲明的接口類型,代碼如下:
type error interface {
Error() string
}所有符合 Error()string 格式的方法,都能實現(xiàn)錯誤接口,Error() 方法返回錯誤的具體描述,使用者可以通過這個字符串知道發(fā)生了什么錯誤。
返回錯誤前,需要定義會產(chǎn)生哪些可能的錯誤,在Go語言中,使用 errors 包進(jìn)行錯誤的定義,格式如下:
var err = errors.New("this is an error")錯誤字符串由于相對固定,一般在包作用域聲明,應(yīng)盡量減少在使用時直接使用 errors.New 返回。
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
}代碼說明如下:
下面的代碼會定義一個除法函數(shù),當(dāng)除數(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
代碼說明:
使用 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ù)錯誤接口具體的類型,獲取詳細(xì)錯誤信息
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
代碼說明如下:
錯誤對象都要實現(xiàn) error 接口的 Error() 方法,這樣,所有的錯誤都可以獲得字符串的描述,如果想進(jìn)一步知道錯誤的詳細(xì)信息,可以通過類型斷言,將錯誤對象轉(zhuǎn)為具體的錯誤類型進(jìn)行錯誤詳細(xì)信息的獲取。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流