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

在golang中使用Sync.WaitGroup解決等待的問(wèn)題

 更新時(shí)間:2021年04月27日 09:53:07   作者:七八月份的太陽(yáng)  
這篇文章主要介紹了在golang中使用Sync.WaitGroup解決等待的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

面對(duì)goroutine我們都需要等待它完成交給它的事情,等待它計(jì)算完成或是執(zhí)行完畢,所以不得不在程序需要等待的地方使用time.Sleep()來(lái)睡眠一段時(shí)間,等待其他goroytine執(zhí)行完畢,下面的代碼打印1到100的for循環(huán)可以在很快的時(shí)間內(nèi)運(yùn)行完畢,但是我們必須添加time.Sleep()來(lái)等待其打印完畢,如果我們不等待仿佛什么也沒(méi)有發(fā)生一樣。。。。。這肯定不是我們想要的!

func main(){
    for i := 0; i < 100 ; i++{
        go fmt.Println(i)
    }
    time.Sleep(time.Second)
}

這就是我最開(kāi)始學(xué)習(xí)goroutine想到的笨方法。。。。死等! 等不到 time.Second*2 在等不到*3

但是對(duì)于我們實(shí)際的使用場(chǎng)景來(lái)說(shuō),1秒也許等待的時(shí)間有點(diǎn)長(zhǎng),而有時(shí)候是遠(yuǎn)遠(yuǎn)不夠的,最主要的我們無(wú)法預(yù)知gorotine的運(yùn)行時(shí)間長(zhǎng)短,所以也無(wú)法指定Sleep睡眠的時(shí)間。

正好前幾天學(xué)習(xí)了channel,那么現(xiàn)在我們就可以

使用channel來(lái)達(dá)到我們的目的了

func main() {
    c := make(chan bool, 100)
    for i := 0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
            c <- true
        }(i)
    }
 
    for i := 0; i < 100; i++ {
        <-c
    }
}

完美輸出!這里我們可以從控制臺(tái)看到我們的勝利成果,但是我們有更好的處理方式:sync.WaitGroup

WaitGroup對(duì)象內(nèi)部有一個(gè)計(jì)數(shù)器,最初從0開(kāi)始,它有三個(gè)方法:Add() Done() Wait() 用來(lái)控制計(jì)數(shù)器的數(shù)量從而達(dá)到等待的目的。

func main() {
   wg := sync.WaitGroup{}
   wg.Add(100)
   for i := 0; i < 100; i++ {
      go func(i int) {
         defer wg.Done()
         fmt.Print(i)
      }(i)
   }
   wg.Wait()
}

首先使用 add(100) 把計(jì)數(shù)器的數(shù)量設(shè)置為100,每次循環(huán)運(yùn)行完畢都把計(jì)數(shù)器減1,主函數(shù)使用Wait()

阻塞,直到計(jì)數(shù)器歸0結(jié)束主線程結(jié)束阻塞。

這里會(huì)阻塞主線程?。。⌒枰⒁?。

另外:以上三種方式打印出的數(shù)字皆無(wú)序

type WaitGroup struct {
 noCopy noCopy
 state1 [3]uint32
}

它只是一個(gè)struct所以當(dāng)參數(shù)傳遞的時(shí)候需要傳遞指針。

補(bǔ)充:sync.WaitGroup的錯(cuò)誤用法與糾正

本文主要是記錄在學(xué)習(xí)golang語(yǔ)言過(guò)程中錯(cuò)誤使用sync.WaitGroup以及指針引起的報(bào)錯(cuò),并且糾正過(guò)程。

1.錯(cuò)誤使用場(chǎng)景

main包的實(shí)現(xiàn)內(nèi)容:

package main
import (
    "fmt"
    "pressure/game"
    "sync"
)
var waitGroup sync.WaitGroup //定義一個(gè)同步等待的組
func main(){
    waitGroup.Add(1) //添加一個(gè)計(jì)數(shù)
    go game.ConnSocket(serverAddr, waitGroup) //調(diào)用其他包的方法執(zhí)行任務(wù)
    waitGroup.Wait() //阻塞直到所有任務(wù)完成
    fmt.Println("main DONE!!!")
}

如下是game包的內(nèi)容:

package game
import (
    "fmt"
    "net"
    "strconv"
    "strings"
    "sync"
)
var gameWait sync.WaitGroup
func ConnSocket(serverAddr string, wait sync.WaitGroup) {
    var err error
    Conn, err = net.Dial("tcp", serverAddr)
    if err != nil {
        fmt.Println("Error connected:", err.Error())
        wait.Done()
        return
    }
    gameWait = wait
    fmt.Println("connected OK:", Conn.RemoteAddr())
    go readMessage()
}
func readMessage() {
    fmt.Println("readMessage:")
    for {
        if OK:=dosomething(),OK{
            gameWait.Done()
        }
    }
}

然后執(zhí)行如上的代碼,會(huì)出現(xiàn)報(bào)錯(cuò):

panic: sync: negative WaitGroup counter

goroutine 12 [running]:

sync.(*WaitGroup).Add(0x7b8b90, 0xffffffffffffffff)

D:/Program Files/Go/src/sync/waitgroup.go:75 +0x1d0

sync.(*WaitGroup).Done(0x7b8b90)

原因:

func ConnSocket(serverAddr string, wait sync.WaitGroup)只是把sync.WaitGroup的值傳遞過(guò)來(lái),而非內(nèi)存地址,所以在賦值給gameWait的時(shí)候也只是賦值了值,gameWait并非指向的main里的waitGroup 的內(nèi)存地址,導(dǎo)致 gameWait.Done()的時(shí)候并沒(méi)有獲取到main里的計(jì)數(shù)1,所以才會(huì)報(bào)負(fù)數(shù)。究其原因還是沒(méi)有對(duì)指針的理解。所以針對(duì)上面的問(wèn)題做了修改。

2.正確的使用

main包的實(shí)現(xiàn)內(nèi)容:

package main
import (
    "fmt"
    "pressure/game"
    "sync"
)
var waitGroup sync.WaitGroup //定義一個(gè)同步等待的組
func main(){
    waitGroup.Add(1) //添加一個(gè)計(jì)數(shù)
    //這里傳遞waitGroup的內(nèi)存地址
    go game.ConnSocket(serverAddr, &waitGroup) //調(diào)用其他包的方法執(zhí)行任務(wù)
    waitGroup.Wait() //阻塞直到所有任務(wù)完成
    fmt.Println("main DONE!!!")
}

如下是game包的內(nèi)容:

package game
import (
    "fmt"
    "net"
    "strconv"
    "strings"
    "sync"
)
var gameWait *sync.WaitGroup//此處也申明為指針變量
//參數(shù)傳遞為指針傳遞*sync.WaitGroup,即wait 指向的是main里的waitGroup的內(nèi)存地址
func ConnSocket(serverAddr string, wait *sync.WaitGroup) {
    var err error
    Conn, err = net.Dial("tcp", serverAddr)
    if err != nil {
        fmt.Println("Error connected:", err.Error())
        wait.Done()
        return
    }
    gameWait = wait//指針指向另一個(gè)指針,這樣就做到了gameWait指向的是wait的地址,所以gameWait修改wait的內(nèi)存地址鎖存貯的值也會(huì)跟隨改變
    fmt.Println("connected OK:", Conn.RemoteAddr())
    go readMessage()
}
func readMessage() {
    fmt.Println("readMessage:")
    for {
        if OK:=dosomething(),OK{
            gameWait.Done()
        }
    }
}

3.結(jié)果

還是對(duì)指針傳遞以及值傳遞理解不夠透徹才會(huì)出現(xiàn)如此問(wèn)題,因此還需要多針對(duì)指針進(jìn)行學(xué)習(xí)與理解。以防在以后的工作中出現(xiàn)類似問(wèn)題。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • Go語(yǔ)言泛型使用及說(shuō)明

    Go語(yǔ)言泛型使用及說(shuō)明

    這篇文章主要介紹了Go語(yǔ)言泛型使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2026-01-01
  • go?time.After優(yōu)化后性能提升34%內(nèi)存減少67%

    go?time.After優(yōu)化后性能提升34%內(nèi)存減少67%

    這篇文章主要介紹了go語(yǔ)言time.After優(yōu)化后性能提升34%內(nèi)存減少67%實(shí)例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 關(guān)于升級(jí)go1.18的goland問(wèn)題詳解

    關(guān)于升級(jí)go1.18的goland問(wèn)題詳解

    作為一個(gè)go語(yǔ)言程序員,覺(jué)得自己有義務(wù)為go新手開(kāi)一條更簡(jiǎn)單便捷的上手之路,下面這篇文章主要給大家介紹了關(guān)于升級(jí)go1.18的goland問(wèn)題的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • Go語(yǔ)言里的new函數(shù)用法分析

    Go語(yǔ)言里的new函數(shù)用法分析

    這篇文章主要介紹了Go語(yǔ)言里的new函數(shù)用法,實(shí)例分析了new函數(shù)的功能及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • golang與pgsql交互的實(shí)現(xiàn)

    golang與pgsql交互的實(shí)現(xiàn)

    本文主要介紹了golang與pgsql交互的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 分享6個(gè)Go處理字符串的技巧小結(jié)

    分享6個(gè)Go處理字符串的技巧小結(jié)

    這篇文章主要介紹了分享6個(gè)Go處理字符串的技巧小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 淺談Go語(yǔ)言中高效并發(fā)模式

    淺談Go語(yǔ)言中高效并發(fā)模式

    Go語(yǔ)言并發(fā)編程提供了豐富的模式,包括基礎(chǔ)Goroutine、Channel和Select機(jī)制,以及多種高級(jí)并發(fā)模式,本文就來(lái)詳細(xì)的介紹一下,感興趣的可以了解一下
    2025-10-10
  • Golang合并yaml文件過(guò)程逐步講解

    Golang合并yaml文件過(guò)程逐步講解

    之前一直從事java開(kāi)發(fā),習(xí)慣了使用yaml文件的格式,尤其是清晰的層次結(jié)構(gòu)、注釋,下面這篇文章主要給大家介紹了關(guān)于Golang合并yaml文件的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • 使用Go快速驗(yàn)證RocketMQ是否正常的完整過(guò)程

    使用Go快速驗(yàn)證RocketMQ是否正常的完整過(guò)程

    最近需要驗(yàn)證一套 RocketMQ 環(huán)境是否可用,最開(kāi)始的訴求很簡(jiǎn)單:我有一個(gè) RocketMQ NameServer 地址,端口是默認(rèn)端口 9876,想確認(rèn)它到底是不是正常,所以本文給大家介紹了如何使用Go快速驗(yàn)證RocketMQ是否正常,需要的朋友可以參考下
    2026-06-06
  • Golang使用Redis與連接池方式

    Golang使用Redis與連接池方式

    這篇文章主要介紹了Golang使用Redis與連接池方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06

最新評(píng)論

仁怀市| 平谷区| 夏邑县| 兰考县| 泰州市| 安多县| 永安市| 来宾市| 外汇| 肃南| 锦屏县| 巴里| 安达市| 山阳县| 西城区| 叙永县| 昭苏县| 泊头市| 松潘县| 抚远县| 孝昌县| 清涧县| 永胜县| 台东市| 娱乐| 瑞丽市| 自治县| 偃师市| 丰顺县| 萨嘎县| 武冈市| 临漳县| 太仆寺旗| 内黄县| 岢岚县| 克拉玛依市| 康平县| 大英县| 建水县| 民县| 安徽省|