最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言動態(tài)并發(fā)控制sync.WaitGroup的靈活運(yùn)用示例詳解

 更新時間:2023年11月22日 11:42:29   作者:Go先鋒  
本文將講解 sync.WaitGroup 的使用方法、原理以及在實(shí)際項(xiàng)目中的應(yīng)用場景,用清晰的代碼示例和詳細(xì)的注釋,助力讀者掌握并發(fā)編程中等待組的使用技巧

概述

在并發(fā)編程中,控制主程序等待所有 Goroutine 完成任務(wù)是一項(xiàng)關(guān)鍵任務(wù)。Go 語言提供了 sync.WaitGroup 來解決這一問題。

1. 基本使用

1.1 初始化和添加計(jì)數(shù)

package main
import (
  "fmt"
  "sync"
  "time"
)
func main() {
  var wg sync.WaitGroup
  for i := 1; i <= 3; i++ {
    wg.Add(1)
    go worker(i, &wg)
  }
  wg.Wait()
  fmt.Println("All workers have completed.")
}
func worker(id int, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Printf("Worker %d started\n", id)
  time.Sleep(2 * time.Second)
  fmt.Printf("Worker %d completed\n", id)
}

在上面示例中,用一個 sync.WaitGroup 實(shí)例 wg,然后使用 wg.Add(1) 來增加計(jì)數(shù),表示有一個 Goroutine 需要等待。

在每個 Goroutine 的結(jié)束處,使用 defer wg.Done() 來減少計(jì)數(shù),表示一個 Goroutine 已完成。

最后,用 wg.Wait() 來等待所有 Goroutine 完成。

1.2 處理錯誤

package main
import (
  "fmt"
  "sync"
  "time"
)
func main() {
  var wg sync.WaitGroup
  for i := 1; i <= 3; i++ {
    wg.Add(1)
    go workerWithError(i, &wg)
  }
  wg.Wait()
  fmt.Println("All workers have completed.")
}
func workerWithError(id int, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Printf("Worker %d started\n", id)
  time.Sleep(2 * time.Second)
  // 模擬錯誤發(fā)生
  if id == 2 {
    fmt.Printf("Worker %d encountered an error\n", id)
    return
  }
  fmt.Printf("Worker %d completed\n", id)
}

有時候,需要在 Goroutine 中處理錯誤。在這個示例中,當(dāng) id 為 2 時,模擬了一個錯誤的情況。

通過在錯誤發(fā)生時提前返回,可以確保計(jì)數(shù)正確減少,避免等待組出現(xiàn)死鎖。

2. 多級等待組

2.1 嵌套使用

package main
import (
  "fmt"
  "sync"
  "time"
)
func main() {
  var outerWG sync.WaitGroup
  var innerWG sync.WaitGroup
  for i := 1; i <= 2; i++ {
    outerWG.Add(1)
    go outerWorker(i, &outerWG, &innerWG)
  }
  outerWG.Wait()
  fmt.Println("All outer workers have completed.")
}
func outerWorker(id int, outerWG, innerWG *sync.WaitGroup) {
  defer outerWG.Done()
  fmt.Printf("Outer Worker %d started\n", id)
  for j := 1; j <= 3; j++ {
    innerWG.Add(1)
    go innerWorker(id, j, innerWG)
  }
  innerWG.Wait()
  fmt.Printf("Outer Worker %d completed\n", id)
}
func innerWorker(outerID, innerID int, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Printf("Inner Worker %d of Outer Worker %d started\n", innerID, outerID)
  time.Sleep(2 * time.Second)
  fmt.Printf("Inner Worker %d of Outer Worker %d completed\n", innerID, outerID)
}

在示例中,使用了嵌套的 sync.WaitGroup。

外部的等待組 outerWG 等待所有外部 Goroutine 完成,而每個外部 Goroutine 內(nèi)部的 innerWG 則等待其內(nèi)部的所有 Goroutine 完成。

2.2 動態(tài)添加等待組

package main
import (
  "fmt"
  "sync"
  "time"
)
func main() {
  var dynamicWG sync.WaitGroup
  for i := 1; i <= 3; i++ {
    dynamicWG.Add(1)
    go dynamicWorker(i, &dynamicWG)
  }
  // 模擬動態(tài)添加更多任務(wù)
  time.Sleep(1 * time.Second)
  for i := 4; i <= 6; i++ {
    dynamicWG.Add(1)
    go dynamicWorker(i, &dynamicWG)
  }
  dynamicWG.Wait()
  fmt.Println("All dynamic workers have completed.")
}
func dynamicWorker(id int, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Printf("Dynamic Worker %d started\n", id)
  time.Sleep(2 * time.Second)
  fmt.Printf("Dynamic Worker %d completed\n", id)
}

在上述示例中,創(chuàng)建了一個等待組 dynamicWG,然后在運(yùn)行時動態(tài)添加了更多的任務(wù)。

用這種方式,可以動態(tài)地管理需要等待的 Goroutine 數(shù)量。   

3. 超時處理

3.1 帶超時的等待

package main
import (
  "fmt"
  "sync"
  "time"
)
func main() {
  var timeoutWG sync.WaitGroup
  for i := 1; i <= 3; i++ {
    timeoutWG.Add(1)
    go timeoutWorker(i, &timeoutWG)
  }
  // 等待最多5秒,超時則不再等待
  timeout := time.After(5 * time.Second)
  done := make(chan struct{})
  go func() {
    timeoutWG.Wait()
    close(done)
  }()
  select {
  case <-done:
    fmt.Println("All timeout workers have completed.")
  case <-timeout:
    fmt.Println("Timeout reached. Not all workers have completed.")
  }
}
func timeoutWorker(id int, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Printf("Timeout Worker %d started\n", id)
  time.Sleep(time.Duration(id) * time.Second)
  fmt.Printf("Timeout Worker %d completed\n", id)
}

在上面示例中,用 time.After 創(chuàng)建了一個 5 秒的超時通道。

在另一個 Goroutine 中監(jiān)聽等待組的完成情況,可以在超時或任務(wù)完成時得知等待的最終結(jié)果。

3.2 處理超時錯誤

package main
import (
  "errors"
  "fmt"
  "sync"
  "time"
)
func main() {
  var timeoutWG sync.WaitGroup
  for i := 1; i <= 3; i++ {
    timeoutWG.Add(1)
    go timeoutWorkerWithError(i, &timeoutWG)
  }
  // 等待最多5秒,超時則返回錯誤
  err := waitWithTimeout(&timeoutWG, 5*time.Second)
  if err != nil {
    fmt.Printf("Timeout reached. Not all workers have completed. Error: %v\n", err)
  } else {
    fmt.Println("All timeout workers have completed.")
  }
}
func timeoutWorkerWithError(id int, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Printf("Timeout Worker %d started\n", id)
  time.Sleep(time.Duration(id) * time.Second)
  // 模擬錯誤發(fā)生
  if id == 2 {
    fmt.Printf("Timeout Worker %d encountered an error\n", id)
    return
  }
  fmt.Printf("Timeout Worker %d completed\n", id)
}
func waitWithTimeout(wg *sync.WaitGroup, timeout time.Duration) error {
  done := make(chan struct{})
  go func() {
    defer close(done)
    wg.Wait()
  }()
  select {
  case <-done:
    return nil
  case <-time.After(timeout):
    return errors.New("timeout reached")
  }
}

有時候,希望在程序超時的時候返回一個錯誤。

在這個示例中,用封裝等待組的超時檢查,可以在主程序中獲得一個清晰的錯誤提示。

總結(jié)

通過討論 sync.WaitGroup 的基本用法、避免常見錯誤以及實(shí)際應(yīng)用,深入了解了這個強(qiáng)大的同步工具。

在 Go 語言并發(fā)編程中,合理使用 sync.WaitGroup 能夠優(yōu)雅地處理并發(fā)等待,確保主程序在所有任務(wù)完成后再繼續(xù)執(zhí)行。

以上就是Go語言動態(tài)并發(fā)控制sync.WaitGroup的靈活運(yùn)用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Go sync.WaitGroup動態(tài)并發(fā)控制的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Go 創(chuàng)建命令行工具的方法

    詳解Go 創(chuàng)建命令行工具的方法

    這篇文章主要介紹了詳解Go 創(chuàng)建命令行工具,需要的朋友可以參考下
    2020-12-12
  • golang使用jaeger進(jìn)行鏈路追蹤

    golang使用jaeger進(jìn)行鏈路追蹤

    鏈路追蹤是指在分布式系統(tǒng)中,將一次請求的處理過程進(jìn)行記錄并聚合展示的一種方法,目的是將一次分布式請求的調(diào)用情況集中在一處展示,本文將介紹golang如何使用jaeger進(jìn)行鏈路追蹤,需要的朋友可以參考下
    2024-06-06
  • golang sync.Pool 指針數(shù)據(jù)覆蓋問題解決

    golang sync.Pool 指針數(shù)據(jù)覆蓋問題解決

    本文主要介紹了使用sync.Pool時遇到指針數(shù)據(jù)覆蓋的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • 通過Golang實(shí)現(xiàn)無頭瀏覽器截圖

    通過Golang實(shí)現(xiàn)無頭瀏覽器截圖

    在Web開發(fā)中,有時需要對網(wǎng)頁進(jìn)行截圖,以便進(jìn)行頁面預(yù)覽、測試等操作,本文為大家整理了Golang實(shí)現(xiàn)無頭瀏覽器的截圖的方法,感興趣的可以了解一下
    2023-05-05
  • 詳解如何在Golang中實(shí)現(xiàn)CORS(跨域)

    詳解如何在Golang中實(shí)現(xiàn)CORS(跨域)

    很多時候,需要允許Web應(yīng)用程序在不同域之間(跨域)實(shí)現(xiàn)共享資源,本文將簡介跨域、CORS的概念,以及如何在Golang中如何實(shí)現(xiàn)CORS,文中有詳細(xì)的示例代碼,需要的朋友可以參考下
    2023-10-10
  • Go語言基礎(chǔ)函數(shù)基本用法及示例詳解

    Go語言基礎(chǔ)函數(shù)基本用法及示例詳解

    這篇文章主要為大家介紹了Go語言基礎(chǔ)函數(shù)基本用法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2021-11-11
  • Go調(diào)用C++動態(tài)庫實(shí)現(xiàn)車牌識別的示例代碼

    Go調(diào)用C++動態(tài)庫實(shí)現(xiàn)車牌識別的示例代碼

    本文主要介紹了如何利用C++中Opencv、TensorRT等庫編譯出動態(tài)庫供Go調(diào)用,再寫個簡單的api對上傳的車輛圖片進(jìn)行車牌識別,文中通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • golang結(jié)構(gòu)化日志log/slog包之LogValuer的用法簡介

    golang結(jié)構(gòu)化日志log/slog包之LogValuer的用法簡介

    這篇文章主要為大家詳細(xì)介紹了golang結(jié)構(gòu)化日志log/slog包中 LogValuer 和日志記錄函數(shù)的正確包裝方法,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-10-10
  • goweb模板語法html/template

    goweb模板語法html/template

    ?在Go語言里, html/template 包主要用于安全地生成HTML輸出,它能夠有效防止跨站腳本攻擊(XSS),借助模板語法將數(shù)據(jù)動態(tài)填充到HTML文件中,下面就來詳細(xì)的介紹一下
    2026-02-02
  • Go語言的type?func()用法詳解

    Go語言的type?func()用法詳解

    在Go語言中,函數(shù)的基本組成為:關(guān)鍵字func、函數(shù)名、參數(shù)列表、返回值、函數(shù)體和返回語句,這篇文章主要介紹了Go語言的type?func()用法,需要的朋友可以參考下
    2022-03-03

最新評論

梅河口市| 牡丹江市| 郧西县| 肃南| 宁波市| 静安区| 水城县| 沙田区| 稻城县| 蒙阴县| 夏邑县| 巍山| 广平县| 察雅县| 巴林左旗| 镇远县| 衡阳县| 长海县| 万载县| 四子王旗| 永修县| 永春县| 景宁| 莱西市| 吉隆县| 晋州市| 商都县| 芜湖市| 余姚市| 栖霞市| 冕宁县| 越西县| 章丘市| 原平市| 六枝特区| 搜索| 黔西县| 博爱县| 买车| 安顺市| 涿州市|