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

Go語言中WaitGroup并發(fā)同步的實現(xiàn)

 更新時間:2026年04月03日 09:59:32   作者:王碼碼2035哦  
本文主要介紹了Go語言中WaitGroup并發(fā)同步的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

寫了十幾年代碼的Go后端老兵。今天聊聊WaitGroup,這個并發(fā)同步的小能手。

一、為什么需要WaitGroup

上周我們重構了一個數(shù)據(jù)導入功能,需要并發(fā)處理多個文件。但程序總是提前退出,有些文件還沒處理完就結束了。

這就是沒有做好并發(fā)同步的后果。WaitGroup可以幫我們等待所有goroutine完成。

二、WaitGroup的基本用法

1. 基礎示例

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1) // 增加計數(shù)器
        go func(id int) {
            defer wg.Done() // 減少計數(shù)器
            fmt.Printf("Worker %d starting\n", id)
            time.Sleep(time.Second)
            fmt.Printf("Worker %d done\n", id)
        }(i)
    }
    wg.Wait() // 等待所有goroutine完成
    fmt.Println("All workers done")
}

2. 錯誤處理

func processFiles(files []string) error {
    var wg sync.WaitGroup
    errChan := make(chan error, len(files))
    for _, file := range files {
        wg.Add(1)
        go func(f string) {
            defer wg.Done()
            if err := processFile(f); err != nil {
                errChan <- err
            }
        }(file)
    }
    wg.Wait()
    close(errChan)
    for err := range errChan {
        if err != nil {
            return err
        }
    }
    return nil
}

三、WaitGroup的實戰(zhàn)技巧

1. 批量處理

func batchProcess(items []Item, batchSize int) {
    var wg sync.WaitGroup
    semaphore := make(chan struct{}, batchSize) // 限制并發(fā)數(shù)
    for _, item := range items {
        wg.Add(1)
        semaphore <- struct{}{} // 獲取信號量
        go func(i Item) {
            defer wg.Done()
            defer func() { <-semaphore }() // 釋放信號量
            process(i)
        }(item)
    }
    wg.Wait()
}

2. 超時控制

func processWithTimeout(items []Item, timeout time.Duration) error {
    var wg sync.WaitGroup
    done := make(chan struct{})
    go func() {
        for _, item := range items {
            wg.Add(1)
            go func(i Item) {
                defer wg.Done()
                process(i)
            }(item)
        }
        wg.Wait()
        close(done)
    }()
    select {
    case <-done:
        return nil
    case <-time.After(timeout):
        return fmt.Errorf("timeout")
    }
}

3. 動態(tài)添加任務

func crawler(urls []string) {
    var wg sync.WaitGroup
    urlChan := make(chan string, 100)
    // 啟動固定數(shù)量的worker
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for url := range urlChan {
                newUrls := fetch(url)
                for _, u := range newUrls {
                    urlChan <- u // 動態(tài)添加新URL
                }
            }
        }()
    }
    // 發(fā)送初始URL
    for _, url := range urls {
        urlChan <- url
    }
    close(urlChan)
    wg.Wait()
}

四、WaitGroup的常見陷阱

1. Add和Done不匹配

// 錯誤:在goroutine內部調用Add
for i := 0; i < 5; i++ {
    go func() {
        wg.Add(1) // 錯誤!可能還沒Add就Wait了
        defer wg.Done()
        // ...
    }()
}
wg.Wait()
// 正確:在啟動goroutine之前Add
for i := 0; i < 5; i++ {
    wg.Add(1)
    go func() {
        defer wg.Done()
        // ...
    }()
}
wg.Wait()

2. 復制WaitGroup

// 錯誤:WaitGroup被復制
func wrong(wg sync.WaitGroup) { // 值傳遞,復制了WaitGroup
    wg.Done()
}
// 正確:傳遞指針
func right(wg *sync.WaitGroup) {
    wg.Done()
}

3. 重復調用Done

// 錯誤:可能調用多次Done
func bad() {
    wg.Add(1)
    go func() {
        defer wg.Done()
        if err := doSomething(); err != nil {
            wg.Done() // 重復調用!
            return
        }
    }()
}

// 正確:只調用一次
func good() {
    wg.Add(1)
    go func() {
        defer wg.Done()
        doSomething()
    }()
}

五、WaitGroup vs Channel

場景推薦方案
等待多個goroutine完成WaitGroup
傳遞數(shù)據(jù)Channel
控制并發(fā)數(shù)Channel(信號量)
錯誤處理Channel + WaitGroup

六、性能優(yōu)化

1. 避免過度并發(fā)

// 不好的做法:無限制并發(fā)
for _, item := range items {
    wg.Add(1)
    go func(i Item) {
        defer wg.Done()
        process(i)
    }(item)
}
// 好的做法:限制并發(fā)數(shù)
semaphore := make(chan struct{}, 10)
for _, item := range items {
    wg.Add(1)
    semaphore <- struct{}{}
    go func(i Item) {
        defer wg.Done()
        defer func() { <-semaphore }()
        process(i)
    }(item)
}

2. 復用goroutine

// 使用worker pool
func workerPool(jobs []Job, workers int) {
    var wg sync.WaitGroup
    jobChan := make(chan Job, len(jobs))
    
    // 啟動固定數(shù)量的worker
    for i := 0; i < workers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for job := range jobChan {
                process(job)
            }
        }()
    }
    
    // 發(fā)送任務
    for _, job := range jobs {
        jobChan <- job
    }
    close(jobChan)
    
    wg.Wait()
}

七、總結

WaitGroup是并發(fā)編程的必備工具,用好它可以:

  • 優(yōu)雅地等待多個goroutine完成
  • 實現(xiàn)復雜的并發(fā)控制邏輯
  • 提高程序的性能和穩(wěn)定性

記?。耗芘芫托?,別折騰。但該用WaitGroup的時候,一定要用對。

到此這篇關于Go語言中WaitGroup并發(fā)同步的實現(xiàn)的文章就介紹到這了,更多相關Go語言 WaitGroup并發(fā)同步內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • GO語言中gox交叉編譯的實現(xiàn)

    GO語言中gox交叉編譯的實現(xiàn)

    本文主要介紹了GO語言中gox交叉編譯的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-11-11
  • Golang中web參數(shù)校驗的實現(xiàn)

    Golang中web參數(shù)校驗的實現(xiàn)

    本文介紹了使用Gin框架進行參數(shù)校驗的幾種方法,包括JSON、URL查詢、表單數(shù)據(jù)的校驗,常用校驗規(guī)則,自定義錯誤信息和自定義校驗規(guī)則,具有一定的參考價值,感興趣的可以了解一下
    2025-11-11
  • 從入門到精通淺析Go語言中如何處理JSON數(shù)據(jù)

    從入門到精通淺析Go語言中如何處理JSON數(shù)據(jù)

    JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,廣泛應用于Web開發(fā)和API設計中,本文將詳細介紹Go語言中的JSON處理,從基礎用法到高級技巧,幫助開發(fā)者掌握JSON處理的各個方面
    2026-04-04
  • Go語言基于Goroutine的超時控制方案設計與實踐

    Go語言基于Goroutine的超時控制方案設計與實踐

    Go語言因其并發(fā)特性而備受青睞,尤其是goroutine和channel的組合,像一對默契的搭檔,為開發(fā)者提供了輕量、高效的并發(fā)工具,下面我們來看看基于goroutine的超時控制方案吧
    2025-05-05
  • Go中使用單調時鐘獲得準確的時間間隔問題

    Go中使用單調時鐘獲得準確的時間間隔問題

    這篇文章主要介紹了Go中使用單調時鐘獲得準確的時間間隔,在go語言中,沒有直接調用時鐘的函數(shù),可以通過?time.Now()?獲得帶單調時鐘的?Time?結構體,并通過Since和Until獲得相對準確的時間間隔,需要的朋友可以參考下
    2022-06-06
  • Go結合Gin導出Mysql數(shù)據(jù)到Excel表格

    Go結合Gin導出Mysql數(shù)據(jù)到Excel表格

    本文主要介紹了Go結合Gin導出Mysql數(shù)據(jù)到Excel表格,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 學會提升Go語言編碼效率技巧拒絕加班!

    學會提升Go語言編碼效率技巧拒絕加班!

    這篇文章主要為大家介紹了Go語言編碼效率提升技巧詳解,學會了從此拒絕加班,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • 關于Go 是傳值還是傳引用?

    關于Go 是傳值還是傳引用?

    這篇文章主要討論Go語言 是傳值還是傳引用?文章先從Go 官方的定義展開,隨后是傳值和傳引用得介紹到map 和 slice得區(qū)別,需要的小伙伴可以參考一下文章得具體內容
    2021-10-10
  • Go語言通道之緩沖通道

    Go語言通道之緩沖通道

    這篇文章介紹了Go語言通道之緩沖通道,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • golang容易導致內存泄漏的6種情況匯總

    golang容易導致內存泄漏的6種情況匯總

    內存泄漏是我們在生產環(huán)境中必須面臨的問題,下面這篇文章主要給大家介紹了關于golang容易導致內存泄漏的6種情況,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-01-01

最新評論

右玉县| 津市市| 岑巩县| 大兴区| 高清| 达日县| 朔州市| 朝阳县| 金坛市| 枣庄市| 耒阳市| 阿图什市| 陆良县| 江达县| 安多县| 保德县| 博客| 五原县| 山东| 台安县| 成安县| 千阳县| 雅江县| 柘荣县| 梨树县| 连山| 商南县| 隆昌县| 连江县| 安仁县| 梨树县| 扎鲁特旗| 运城市| 金塔县| 拉萨市| 潼南县| 宝清县| 扶风县| 西林县| 合肥市| 民县|