go語言異常處理


go語言異常處理

error接口

go語言引入了一個關於錯誤錯里的標准模式,即error接口,該接口的定義如下:

type error interface{
	Error() string
}

對於要返回錯誤的大多數函數來說,大致上都可以定義為如下的模式,將error作為多個返回值中的最后一個,但是這並非是強制要求

func Foo(param int) (n int,err error){
	//
}

調用該函數的時候建議按照如下的方式處理錯誤情況

n,err := Foo(0)
if err != nil{
	//處理錯誤
}else{
	//處理結果
}

那么,如何自定義error類型呢,我們以Go庫中的實際代碼為例來說明,首先,定義一個承載錯誤信息的類型,因為Go中的接口非常的靈活,你根本不需要像別的語言一樣使用繼承或則implements來明確指定類型和接口之間的關系,代碼如下:

type PathError struct{
Op string
Path string
Err error
}

這樣定義后,編譯器如何知道PathError可以當成一個error來傳遞呢?關鍵在於下面的代碼實現了Error() 方法:

func (e *PathError) Error() string{
	return e.Op + " " + e.Path +" " + e.Err.Error()
}

定義了上述方法之后,就可以直接返回PathError變量了,如下:

func test(name string) (fi FIleInfo,err error){
var stat syscall.Stat_t
err = syscall.Stat(name,&stat)
if err != nil{
return nil,$PathError{"stat",name,err}
}
return file,nil
}

如果在處理錯誤的時候要獲取錯誤的詳細信息,就需要用到類型的轉換知識了:

fi,err := os.Stat("a.txt")
if err != nil{
	if e,ok := err.(*os.PathError);ok && e.Err != nil{
		//獲取PathError類型變量e總的其他信息
	}
}

defer

關鍵字defer是Go引入的一個很有意思的特性,他能保證在函數中發生異常的情況下,defer定義的語句仍然會被執行,如下:

func CopyFile(dst,src string) (w int64,err error){
	srcFile,err := os.Open(src)
	if err != nil{
		return	
	}
	defer srcFile.Close()
	dstFile,err := os.Create(dst)
	if err != nil{
		return
	}
	defer dstFile.Close()
	return io.Copy(dstFile,srcFile)
}

即使Copy函數拋出異常,Go仍然會保證文件被正常的關閉,如果據的一句話干不完清理工作的話,可以在defer后加一個匿名函數:

defer func(){
	//
}()

值得注意的是一個函數中可以定義多個defer,並且defer語句的順序是按照先進后出的順序執行的,也就是說最后一個defer語句將最先被執行

panic()和recover()

GO引入了兩個內置的函數panic()和recover()以報告和處理運行時錯誤和程序中的錯誤場景

func panic(interface{})
func recover() interface{}

當在一個函數中調用panic函數后,正確的執行流程會被立即終止,但函數中之前使用defer關鍵字延遲執行的語句將正常展開執行,之后該函數將返回到調用函數,並導致逐步向上執行panic流程,直到所屬的goroutine中所有正在執行的函數被終止,錯誤信息將被報告,這個過程成為錯誤處理流程

從panic中傳入的interface{}中我們可以看出,該函數接收任意類型的數據

recover用於終止錯誤處理流程,一般情況下,recover應該在一個使用defer關鍵字的函數中執行以有效截取錯誤處理流程,如果在發生異常的goroutine中沒有調用recover,會導致該goroutine所屬的進程直接退出

下面是一個常用的場景

defer func(){
	if r := recover();r!=nil{
		log.Printf("Runtime error caught: %v",r)
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM