欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

重學(xué)Go語言之錯誤處理與異常機制詳解

 更新時間:2023年08月27日 08:41:38   作者:程序員讀書  
Go語言的開發(fā)者顯然覺得?try-catch被濫用了,因此?Go不支持使用?try-catch語句捕獲異常處理,那么,Go語言是如何定義和處理程序的異常呢,下面我們就來看看吧

作為開發(fā)者來說,我們沒辦法保證程序在運行過程中永遠不會出現(xiàn)異常,對于異常,在很多編程語言中,可以用 try-catch語句來捕獲,而Go語言的開發(fā)者顯然覺得 try-catch被濫用了,因此 Go不支持使用 try-catch語句捕獲異常處理。

那么,Go語言是如何定義和處理程序的異常呢?

Go語言的將程序運行出現(xiàn)的問題分為兩種:錯誤(error)和異常(exception),錯誤是程序(比如一個函數(shù))運行的預(yù)期結(jié)果之一,當你調(diào)用一個函數(shù)時,就應(yīng)該處理出現(xiàn)錯誤的情況,而異常是不可預(yù)期的(當然也可以手動觸發(fā))且會導(dǎo)致程序中斷運行的嚴重錯誤。

Go錯誤處理策略

編寫Go語言程序,一般推薦通過函數(shù)的最后一個返回值告訴調(diào)用者函數(shù)是否執(zhí)行成功,可以分兩種情況來討論:

第一種情況,如果函數(shù)的執(zhí)行結(jié)果只有正確與失敗,那么返回值可以是 boolean類型:

func exists(key string) bool {
	//to check if the key is exists
	return true
}
if ok := exists("test"); ok {
	// do something
}

第二種情況,如果要讓調(diào)用者得到更詳細的錯誤信息,顯然只返回一個布爾值是不夠的,這時候可以返回一個 error類型,error類型是一個接口,只有一個 Error方法的接口:

type error interface {
	Error() string
}

通過 error類型的 Error方法,可以獲得更詳細的錯誤信息,方便調(diào)用者做進一步的處理,因此在 Go標準庫的方法和函數(shù)中,一般都會將 error類型作為最后一個返回值,比如我們以前文章中講到的 os包下的 OpenCreate函數(shù):

package os
func Open(name string) (*File, error) {
	return OpenFile(name, O_RDONLY, 0)
}
func Create(name string) (*File, error) {
	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

當函數(shù)最后一個返回值 error不為 nil時,表示執(zhí)行不成功,此時其他的返回值就應(yīng)該忽略:

file,err := os.Open("./my.dat")
if err != nil{
  	return err
}
defer file.Close()

上面代碼中,如果 error不為 nil,那么變量 file則為 nil,表示無法獲得一個文件句柄,這時候直接返回錯誤,因為如果再繼續(xù)往下執(zhí)行,可能會引發(fā)程序崩潰。

當然并不是所有情況下一遇到返回的 error不為 nil,就要拋棄其他返回值,比如使用 Read()方法讀取文件時:

Read(p []byte) (n int, err error)

在讀取文件到結(jié)尾時 Read方法會返回一個 io.EOF的錯誤:

var EOF = errors.New("EOF")

此時雖然 error不為 nil,但仍然應(yīng)該把讀取到的字節(jié)數(shù)組保存,而不是拋棄掉。

創(chuàng)建error的幾種方式

當我們開發(fā)自己的函數(shù)時,也可以創(chuàng)建自己的錯誤類型,有以下幾種方式:

errors包

errors包下的 New()函數(shù)可以創(chuàng)建一個只有文本信息的 error類型:

func getFile(name string)(*os.file,error){
	if name == ""{
		return nil,errors.New("file name could not be empty") 
	}
}

fmt包

fmt包下的 Errorf函數(shù)可以將文本格式后作為error類型的錯誤信息,并返回一個error類型,因此其作用與errors.New函數(shù)類似

func getFile(name string)(*os.file,error){
	if name == ""{
		return nil,fmt.Errorf("file name could not be empty")
	}
}

fmt.Errorf函數(shù)還能封裝其他 error類型,再返回一個新的 error類型,以此形成一條完整的錯誤鏈條:

doc, err := html.Parse(resp.Body)
resp.Body.Close()
if err != nil {
	return nil, fmt.Errorf("parsing %s as HTML: %v", url,err)
}

自定義錯誤類型

其實,上面兩種創(chuàng)建錯誤類型的方式,本質(zhì)上都是實現(xiàn) error接口,我們也可以創(chuàng)建一個擁有 Error方法的類型來實現(xiàn) error接口:

type Result struct {
	Code    int
	Message string
	Data    interface{}
}
func (r Result) Error() string {
	return r.Message
}

如何處理錯誤

當調(diào)用的函數(shù)或方法的返回值有 error類型時,最簡單的當然可以選擇直接忽略錯誤,不過更恰當?shù)姆绞绞翘幚韺?yīng)的錯誤,有以下幾種處理策略:

直接返回錯誤

對于函數(shù)來說,如果在執(zhí)行時遇到錯誤,可以直接返回給上層調(diào)用者:

func SendMessage(url string) error {
	if url == ""{
		return errors.New("url can't not be empty")
	}
	_, err := http.Get(url)
	if err != nil {
		return err
	}
	return nil
}

記錄日志并繼續(xù)運行

當調(diào)用函數(shù)時遇到返回的錯誤,如果不影響程序運行,也可以選擇記錄錯誤日志并往下執(zhí)行:

if err := SendMessage("https://xxx/sendMessage");err != nil{
	log.Printf("the message sending been broken by : %v\n", err)
}

記錄日志并結(jié)束運行

如果錯誤影響程序的執(zhí)行,也可以記錄日志后,退出程序執(zhí)行:

if err := SendMessage("https://xxx/sendMessage");err != nil{
	log.Printf("the message sending been broken by : %v\n", err)
	os.Exit(1)
}

記錄日志并退出執(zhí)行,直接用 log包的 Fatalf函數(shù)就可以做到,因此上面代碼的更簡潔做法是:

if err := SendMessage("https://xxx/sendMessage");err != nil{
	log.Fatalf("the message sending been broken by : %v\n", err)
}

Go異常處理機制

在Go語言中,異常是指會引發(fā)程序崩潰無法繼續(xù)運行的錯誤,比如數(shù)組越界或者空指針引用等情況,這時候會觸發(fā) panic異常:

package main
func main() {
	var s = []int{1, 2, 3}
	s[3] = 10
}

上面程序運行結(jié)果如下,可以看出觸發(fā)了數(shù)組越界的異常:

panic: runtime error: index out of range [3] with length 3

無論是在主協(xié)程還是子協(xié)程中,一旦觸發(fā) panic異常,整個程序都會終止運行。

panic函數(shù)

除了數(shù)組越界等不可預(yù)測的異常會自動觸發(fā) panic,也可以手動調(diào)用 panic函數(shù)觸發(fā)異常來終止程序的運行:

func loadConfig(path string){
	panic("can't load the config file on path " + path)
}

一個良好的程序最好不要主動調(diào)用 panic函數(shù),尤其是開發(fā)類庫的時候,最好通過返回 error類型來告訴調(diào)用者發(fā)生了什么錯誤,而不是觸發(fā) panic導(dǎo)致程序終止運行。

recover函數(shù)

當發(fā)生 panic異常時,如果不捕獲得異常,那么程序就是終止運行,在Go語言中,可以用 defer語句和 recover函數(shù)的模式來捕獲 panic異常:

package main
import (
	"fmt"
	"log"
)
func main() {
	n1 := FindElementByIndex(1)
	fmt.Println(n1)
	n2 := FindElementByIndex(4)
	fmt.Println(n2)
}
func FindElementByIndex(index int) int {
	defer func() {
		if e := recover(); e != nil {
			log.Fatal(e)
		}
	}()
	s := []int{1, 2, 3, 4}
	return s[index]
}

小結(jié)

調(diào)用函數(shù)時,錯誤是執(zhí)行的結(jié)果,應(yīng)該及時處理,而異常往往不可控,可以用defer+recover的模式進行捕獲。

到此這篇關(guān)于重學(xué)Go語言之錯誤處理與異常機制詳解的文章就介紹到這了,更多相關(guān)Go錯誤處理與異常機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言簡易圖像驗證碼生成的實戰(zhàn)案例

    Go語言簡易圖像驗證碼生成的實戰(zhàn)案例

    本篇我們將使用Go語言結(jié)合第三方庫 github.com/mojocn/base64Captcha,快速實現(xiàn)一個簡易圖像驗證碼生成接口,具有一定的參考價值,感興趣的可以了解一下
    2025-08-08
  • Go語言題解LeetCode1051高度檢查器示例詳解

    Go語言題解LeetCode1051高度檢查器示例詳解

    這篇文章主要為大家介紹了Go語言題解LeetCode1051高度檢查器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • 詳解Go?將在下個版本支持新型排序算法pdqsort

    詳解Go?將在下個版本支持新型排序算法pdqsort

    這篇文章主要介紹了Go?將在下個版本支持新型排序算法:pdqsort,而就Go支持pdqsort算法,在HN上引起了不少的討論,有人表示,我們研究排序算法這么久了,很驚訝我們還能想出能產(chǎn)生實際改進的優(yōu)化方案。對此,你怎么看,快快上手體驗一下吧
    2022-04-04
  • Go語言正則表達式用法實例小結(jié)【查找、匹配、替換等】

    Go語言正則表達式用法實例小結(jié)【查找、匹配、替換等】

    這篇文章主要介紹了Go語言正則表達式用法,結(jié)合實例形式分析了Go語言基于正則實現(xiàn)查找、匹配、替換等基本操作的實現(xiàn)技巧,需要的朋友可以參考下
    2017-01-01
  • Go底層之singleflight包原理分析

    Go底層之singleflight包原理分析

    這篇文章主要介紹了Go底層之singleflight包原理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • Golang中單引號、雙引號、反引號的實現(xiàn)

    Golang中單引號、雙引號、反引號的實現(xiàn)

    Go語言中單引號表示rune類型,雙引號用于字符串支持轉(zhuǎn)義,反引號保留原始內(nèi)容且支持多行不轉(zhuǎn)義,三者區(qū)分關(guān)鍵在于字符處理方式與轉(zhuǎn)義規(guī)則,下面就來介紹一下
    2025-06-06
  • Go 1.13中errors包的新變化示例解析

    Go 1.13中errors包的新變化示例解析

    這篇文章主要為大家介紹了Go 1.13中errors包的新變化示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • golang解析xml的方法

    golang解析xml的方法

    這篇文章主要介紹了golang解析xml的方法,結(jié)合實例形式分析了Go語言針對xml文件的讀取與解析的相關(guān)技巧,需要的朋友可以參考下
    2016-07-07
  • Go高級特性探究之處理1分鐘百萬請求詳解

    Go高級特性探究之處理1分鐘百萬請求詳解

    對于大型的互聯(lián)網(wǎng)應(yīng)用程序,如電商平臺、社交網(wǎng)絡(luò)、金融交易平臺等,每秒鐘都會收到大量的請求,那么Go是如何處理這些百萬請求的呢,下面就來和大家詳細講講
    2023-06-06
  • Golang基于sync.Once實現(xiàn)單例的操作代碼

    Golang基于sync.Once實現(xiàn)單例的操作代碼

    這篇文章主要介紹了golang實現(xiàn)單例的操作代碼,本文介紹基于sync.Once的方式來實現(xiàn)單例,熟練掌握這種模式,并理解其底層原理,對大部分人來講已經(jīng)完全夠用了,需要的朋友可以參考下
    2022-10-10

最新評論