国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

技巧分享:多 Goroutine 如何優雅處理錯誤?

開發 后端
在 Go 語言中 goroutine 是非常常用的一種方法,為此我們需要更了解 goroutine 配套的上下游(像是 context、error 處理等),應該如何用什么來保證。

[[409241]]

本文轉載自微信公眾號「腦子進煎魚了」,作者陳煎魚。轉載本文請聯系腦子進煎魚了公眾號。

大家好,我是煎魚。

在 Go 語言中,goroutine 的使用是非常頻繁的,因此在日常編碼的時候我們會遇到一個問題,那就是 goroutine 里面的錯誤處理,怎么做比較好?

這是來自我讀者群的問題。作為一個寵粉煎魚,我默默記下了這個技術話題。今天煎魚就大家來看看多 goroutine 的錯誤處理機制也有哪些!

一般來講,我們的業務代碼會是:

  1. func main() { 
  2.  var wg sync.WaitGroup 
  3.  wg.Add(2) 
  4.  go func() { 
  5.   log.Println("腦子進煎魚了"
  6.   wg.Done() 
  7.  }() 
  8.  go func() { 
  9.   log.Println("煎魚想報錯..."
  10.   wg.Done() 
  11.  }() 
  12.  
  13.  time.Sleep(time.Second

在上述代碼中,我們運行了多個 goroutine。但我想拋出 error 的錯誤信息出來,似乎沒什么好辦法...

通過錯誤日志記錄

為此,業務代碼中常見的第一種方法:通過把錯誤記錄寫入日志文件中,再結合相關的 logtail 進行采集和梳理。

但這又會引入新的問題,那就是調用錯誤日志的方法寫的到處都是。代碼結構也比較亂,不直觀。

最重要的是無法針對 error 做特定的邏輯處理和流轉。

利用 channel 傳輸

這時候大家可能會想到 Go 的經典哲學:不要通過共享內存來通信,而是通過通信來實現內存共享(Do not communicate by sharing memory; instead, share memory by communicating)。

第二種的方法:利用 channel 來傳輸多個 goroutine 中的 errors:

  1. func main() { 
  2.  gerrors := make(chan error) 
  3.  wgDone := make(chan bool) 
  4.  
  5.  var wg sync.WaitGroup 
  6.  wg.Add(2) 
  7.  
  8.  go func() { 
  9.   wg.Done() 
  10.  }() 
  11.  go func() { 
  12.   err := returnError() 
  13.   if err != nil { 
  14.    gerrors <- err 
  15.   } 
  16.   wg.Done() 
  17.  }() 
  18.  
  19.  go func() { 
  20.   wg.Wait() 
  21.   close(wgDone) 
  22.  }() 
  23.  
  24.  select { 
  25.  case <-wgDone: 
  26.   break 
  27.  case err := <-gerrors: 
  28.   close(gerrors) 
  29.   fmt.Println(err) 
  30.  } 
  31.  
  32.  time.Sleep(time.Second
  33.  
  34. func returnError() error { 
  35.  return errors.New("煎魚報錯了..."

輸出結果:

  1. 煎魚報錯了... 

雖然使用 channel 后已經方便了不少。但自己編寫 channel 總是需要關心一些非業務向的邏輯。

借助 sync/errgroup

因此第三種方法,就是使用官方提供的 sync/errgroup 標準庫:

  1. type Group 
  2.     func WithContext(ctx context.Context) (*Group, context.Context) 
  3.     func (g *Group) Go(f func() error) 
  4.     func (g *Group) Wait() error 
  • Go:啟動一個協程,在新的 goroutine 中調用給定的函數。
  • Wait:等待協程結束,直到來自 Go 方法的所有函數調用都返回,然后返回其中的第一個非零錯誤(如果有的話)。

結合其特性能夠非常便捷的針對多 goroutine 進行錯誤處理:

  1. func main() { 
  2.  g := new(errgroup.Group
  3.  var urls = []string{ 
  4.   "http://www.golang.org/"
  5.   "https://golang2.eddycjy.com/"
  6.   "https://eddycjy.com/"
  7.  } 
  8.  for _, url := range urls { 
  9.   url := url 
  10.   g.Go(func() error { 
  11.    resp, err := http.Get(url) 
  12.    if err == nil { 
  13.     resp.Body.Close() 
  14.    } 
  15.    return err 
  16.   }) 
  17.  } 
  18.  if err := g.Wait(); err == nil { 
  19.   fmt.Println("Successfully fetched all URLs."
  20.  } else { 
  21.   fmt.Printf("Errors: %+v", err) 
  22.  } 

在上述代碼中,其表現的是爬蟲的案例。每一個計劃新起的 goroutine 都直接使用 Group.Go 方法。在等待和錯誤上,直接調用 Group.Wait 方法就可以了。

使用標準庫 sync/errgroup 這種方法的好處就是不需要關注非業務邏輯的控制代碼,比較省心省力。

進階使用

在真實的工程代碼中,我們還可以基于 sync/errgroup 實現一個 http server 的啟動和關閉 ,以及 linux signal 信號的注冊和處理。以此保證能夠實現一個 http server 退出,全部注銷退出。

參考代碼(@via 毛老師)如下:

  1. func main() { 
  2.  g, ctx := errgroup.WithContext(context.Background()) 
  3.  svr := http.NewServer() 
  4.  // http server 
  5.  g.Go(func() error { 
  6.   fmt.Println("http"
  7.   go func() { 
  8.    <-ctx.Done() 
  9.    fmt.Println("http ctx done"
  10.    svr.Shutdown(context.TODO()) 
  11.   }() 
  12.   return svr.Start() 
  13.  }) 
  14.  
  15.  // signal 
  16.  g.Go(func() error { 
  17.   exitSignals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT} // SIGTERM is POSIX specific 
  18.   sig := make(chan os.Signal, len(exitSignals)) 
  19.   signal.Notify(sig, exitSignals...) 
  20.   for { 
  21.    fmt.Println("signal"
  22.    select { 
  23.    case <-ctx.Done(): 
  24.     fmt.Println("signal ctx done"
  25.     return ctx.Err() 
  26.    case <-sig: 
  27.     // do something 
  28.     return nil 
  29.    } 
  30.   } 
  31.  }) 
  32.  
  33.  // inject error 
  34.  g.Go(func() error { 
  35.   fmt.Println("inject"
  36.   time.Sleep(time.Second
  37.   fmt.Println("inject finish"
  38.   return errors.New("inject error"
  39.  }) 
  40.  
  41.  err := g.Wait() // first error return 
  42.  fmt.Println(err) 

內部基礎框架有非常有這種代碼,有興趣的可以自己模仿著寫一遍,收貨會很多。

總結

在 Go 語言中 goroutine 是非常常用的一種方法,為此我們需要更了解 goroutine 配套的上下游(像是 context、error 處理等),應該如何用什么來保證。

 

再在團隊中形成一定的共識和規范,這么工程代碼閱讀起來就會比較的舒適,一些很坑的隱藏 BUG 也會少很多 :)

 

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2021-08-10 07:41:24

ContextWaitGroupGoroutine

2024-01-15 08:09:44

Fluent錯誤代碼

2022-02-15 08:38:04

錯誤邏輯異常編程程序

2024-10-16 12:23:55

技巧Spring驗證

2021-09-08 09:41:09

開發Go代碼

2023-10-10 13:23:18

空指針異常Java

2021-06-17 09:32:39

重復請求并發請求Java

2017-12-14 14:17:08

Windows使用技巧手冊

2025-02-10 09:49:00

2022-03-25 06:26:57

WiFi密碼路由器

2025-01-20 07:10:00

LambdaJavanull

2024-09-24 10:16:13

PythonWord文檔

2021-06-09 07:15:20

Go枚舉技巧

2023-05-12 12:09:38

職責鏈模式客服

2021-04-19 07:41:37

AcceptEmfile問題

2023-11-06 09:32:52

Java實踐

2021-12-07 05:53:36

IDMWindows 運維

2009-12-15 10:23:23

Ruby應用技巧

2022-05-10 08:17:03

goroutine泄漏

2022-08-03 07:07:10

Spring數據封裝框架
點贊
收藏

51CTO技術棧公眾號

中文字幕亚洲乱码| 成人影院中文字幕| 日韩一区日韩二区| 中文字幕免费高| 成年人免费大片| 免费视频久久| 91香蕉电影院| 97精品视频| 国产精品亚洲综合天堂夜夜| 精品三级av| 精品国产三区在线| 国产一区二区三区免费视频| 波多野结衣视频一区二区| 国产在线不卡一区| 欧美午夜片在线观看| 91最新在线| 在线精品视频小说1| 少妇激情一区二区三区| 成人一区二区在线观看| 国产一区二区三区在线免费| 婷婷成人av| 亚洲一区二区三| 欧美经典影片视频网站| www.久久久久久.com| 国产精品无码一本二本三本色| 成人午夜电影小说| av在线播放天堂| 99视频精品免费视频| 男女av免费观看| 亚洲同性gay激情无套| 三级国产三级在线| 欧美色图一区二区三区| 成人三级网址| 亚洲精品视频久久| 成人网av.com/| 人人爽久久涩噜噜噜网站| 熟女熟妇伦久久影院毛片一区二区| 久久精品国产秦先生| 97中文字幕在线| 中文字幕在线观看一区二区| 在线资源av| 欧美精品第1页| 成人啊v在线| 日韩av免费看网站| 激情综合久久| 99精品视频网站| 欧美激情综合五月色丁香| 黄污在线观看| 亚洲国产精品成人精品| av动漫精品一区二区| 成人永久免费| 国产成人免费视频网站| av男人的天堂网| 3d动漫精品啪啪1区2区免费| 欧美自拍电影| 日韩av理论片| 美女性感视频久久| 国产免播放器视频| 精品国产91九色蝌蚪| 极品束缚调教一区二区网站 | 麻豆导航在线观看| 涩涩涩久久久成人精品| 国产aⅴ精品一区二区三区黄| 日韩欧美中文字幕精品| 国产在线1区| 亚洲夜晚福利在线观看| 国产大陆a不卡| 成人午夜影院| 另类小说欧美激情| 欧美在线观看视频网站| 一本一本大道香蕉久在线精品| 欧美日韩系列| 日韩中文字幕在线免费观看| 国产一区视频网站| 香港三级日本三级a视频| 亚洲男同1069视频| 久久精品国产96久久久香蕉| 国产米奇在线777精品观看| 黄色激情网站| 91视视频在线观看入口直接观看www | 97超超碰碰| 亚洲免费福利视频| 动漫av一区| 日韩一区二区三区在线播放| 欧美日韩在线二区| 亚洲视频在线观看日本a| 日韩毛片精品高清免费| caopon在线免费视频| 国模视频一区二区| 日韩中文字幕一区二区三区| 成人网免费看| 亚洲第一区在线| 日韩精品一卡| 少妇人妻在线视频| 欧美一区在线视频| 九九久久电影| www精品久久| 欧美色倩网站大全免费| 网曝91综合精品门事件在线| 中文字幕精品—区二区| 亚洲国产精品精华液网站| 日韩av成人| 色乱码一区二区三区88| 免费看日产一区二区三区| 欧美二级三级| 岛国av在线不卡| 高清一区二区三区| 国产人妻人伦精品| 欧美日韩免费在线视频| 欧美爱爱网站| www.中文字幕在线| 日韩不卡在线观看| 亚洲美女少妇无套啪啪呻吟| 91在线网站| 91精品国产91久久久久久最新| 国产成人丝袜美腿| 888av在线视频| 久久riav二区三区| 岛国av一区二区| 国产不卡一区| 四虎av网址| 欧美精品成人91久久久久久久| 成人午夜免费电影| 欧美性猛交xxx高清大费中文| 四虎永久国产精品| 日韩欧美激情一区| 久久婷婷丁香| 欧美乱人伦中文字幕在线| 国产乱码精品一区二区三区忘忧草| av小次郎在线| 欧美美乳视频网站在线观看| 在线精品视频小说1| 伊人久久大香线| 午夜在线观看91| 91精品在线影院| 亚洲18女电影在线观看| 欧美mv日韩| 日韩一二三四| av电影成人| 欧美日韩视频在线第一区 | 日韩av网站在线免费观看| 一二三四视频社区在线| 亚洲日韩中文字幕| 国产精品996| 奇米777日韩| 91免费黄视频| 欧美成人免费大片| 国产欧美精品国产国产专区| 在线一区二区三区视频| 亚洲精品中文字幕无码蜜桃| 性欧美亚洲xxxx乳在线观看| 国产精品久久久久久妇女6080| 免费观看成人www动漫视频| 99在线欧洲视频| 国产日韩欧美一二三区| 91精品办公室少妇高潮对白| 在线观看视频日韩| 伦理在线一区| 亚洲人精品午夜射精日韩 | 免费观看一级欧美片| 久久久久久久久久网| 欧美激情国内偷拍| 亚洲第一主播视频| 国产精品一国产精品k频道56| 国产福利在线免费观看| 日韩一区二区高清视频| 欧美国产中文字幕| 午夜视频在线观看一区| 影音先锋亚洲一区| 忘忧草在线影院两性视频| 人妻熟女一二三区夜夜爱| 日韩av电影免费观看高清| 一本色道综合亚洲| 日本va欧美va瓶| 日本精品在线播放| 在线亚洲电影| 日本午夜精品电影| 久久伊人精品天天| 亚洲成av人**亚洲成av**| 亚洲第一黄网| 国产精品一区二区免费福利视频| 8848hh四虎| 国产精品三级久久久久三级| 亚洲深深色噜噜狠狠爱网站| 久久青青色综合| 少妇人妻互换不带套| 福利视频一区二区三区| 亚洲色图五月天| 亚洲国产精品一区二区www| 日本一不卡视频| 久久中文字幕导航| 国产精品国精产品一二| 成年免费网站| 亚洲欧洲在线一区| 欧美亚洲日本黄色| 精品少妇一区二区三区日产乱码 | 久久久久久久免费| 久久影视电视剧免费网站清宫辞电视 | 国产v综合ⅴ日韩v欧美大片| 日韩午夜中文字幕|