目錄
- 前言
- 通過錯(cuò)誤日志記錄
- 利用 channel 傳輸
- 使用 sync/errgroup
- 總結(jié)
前言
在 Go 語言程序開發(fā)中,goroutine 的使用是比較頻繁的,因此在日常編碼的時(shí)候 goroutine 里的錯(cuò)誤處理,怎么做會(huì)比較好呢?
一般我們的業(yè)務(wù)代碼如下:
func main() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
//... 業(yè)務(wù)邏輯
wg.Done()
}()
go func() {
//... 業(yè)務(wù)邏輯
wg.Done()
}()
wg.Wait()
}
在上面的代碼中,我們運(yùn)行了多個(gè) goroutine,每個(gè)協(xié)程又是單獨(dú)行動(dòng)的,想要拋出 error 錯(cuò)誤信息,也不怎么明智。
通過錯(cuò)誤日志記錄
常用的第一種方法:通過把錯(cuò)誤記錄寫入到日志文件中,再結(jié)合相關(guān)的 logtail 進(jìn)行采集和梳理。
但這又會(huì)引入新的問題,那就是調(diào)用錯(cuò)誤日志的方法寫的到處都是,代碼結(jié)構(gòu)也比較亂、不直觀。
最重要的是無法針對(duì) error 做特定的邏輯處理和流轉(zhuǎn)。
利用 channel 傳輸
大家可能會(huì)想到 Go 的經(jīng)典哲學(xué):不要通過共享內(nèi)存來通信,而是通過通信來實(shí)現(xiàn)內(nèi)存共享(Do not communicate by sharing memory; instead, share memory by communicating)。
第二種方法:利用 channel 來傳輸多個(gè) goroutine 中的 errors:
func main() {
cherrors := make(chan error)
wgDone := make(chan bool)
var wg sync.WaitGroup
wg.Add(2)
go func() {
//... 業(yè)務(wù)邏輯
wg.Done()
}()
go func() {
//... 業(yè)務(wù)邏輯
err := returnErr()
if err != nil {
cherrors - err
}
wg.Done()
}()
go func() {
wg.Wait()
close(wgDone)
}()
select {
case -wgDone:
break
case err := -cherrors:
close(cherrors)
fmt.Println(err)
}
time.Sleep(time.Second)
}
func returnErr() error {
return errors.New("出錯(cuò)啦。。我是錯(cuò)誤信息")
}
雖然使用 channel 后已經(jīng)方便了不少,但編寫 channel 還要關(guān)心一些非業(yè)務(wù)向的邏輯。
使用 sync/errgroup
第三種方法,就是使用官方提供的 golang.org/x/sync/errgroup
標(biāo)準(zhǔn)庫:
type Group
func WithContext(ctx context.Context) (*Group, context.Context)
func (g *Group) Go(f func() error)
func (g *Group) Wait() error
- Go:?jiǎn)?dòng)一個(gè)協(xié)程,在新的 goroutine 中調(diào)用給定的函數(shù)。
- Wait:等待協(xié)程結(jié)束,直到 Go 方法中的所有函數(shù)調(diào)用都返回,然后返回其中第一個(gè)非零錯(cuò)誤(如果有錯(cuò)誤的話)。
結(jié)合其特性能夠非常便捷的針對(duì)多 goroutine 進(jìn)行錯(cuò)誤處理:
func main() {
group := new(errgroup.Group)
nums := []int{-1, 0, 1}
for _, num := range nums {
num := num
group.Go(func() error {
res, err := output(num)
fmt.Println(res)
return err
})
}
if err := group.Wait(); err != nil {
fmt.Println("Get errors: ", err)
} else {
fmt.Println("Get all num successfully!")
}
}
func output(num int) (int, error) {
if num 0 {
return 0, errors.New("math: square root error!")
}
return num, nil
}
每啟動(dòng)一個(gè)新的 goroutine 都直接使用 Group.Go
方法,在等待和錯(cuò)誤處理上使用 Group.Wait
方法。
這種方法進(jìn)行錯(cuò)誤處理的好處是不需要關(guān)注非業(yè)務(wù)邏輯的控制代碼,比較簡(jiǎn)潔明了。
總結(jié)
在 Go 語言中,goroutine 是一種常用的方法,為此我們需要更了解 goroutine 的一系列相關(guān)知識(shí),像是 context、error處理等
在團(tuán)隊(duì)開發(fā)中,統(tǒng)一一定的規(guī)范,這樣的代碼閱讀起來就會(huì)比較明朗,一些隱藏很深的 Bug 也會(huì)減少很多。
到此這篇關(guān)于go goroutine 怎樣進(jìn)行錯(cuò)誤處理的文章就介紹到這了,更多相關(guān)go goroutine 錯(cuò)誤處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)
- 詳解Go語言的錯(cuò)誤處理和資源管理
- 詳解Go多協(xié)程并發(fā)環(huán)境下的錯(cuò)誤處理
- Golang中重復(fù)錯(cuò)誤處理的優(yōu)化方法
- Golang巧用defer進(jìn)行錯(cuò)誤處理的方法
- Go語言中更優(yōu)雅的錯(cuò)誤處理
- Go語言中錯(cuò)誤處理實(shí)例分析
- GO語言標(biāo)準(zhǔn)錯(cuò)誤處理機(jī)制error用法實(shí)例