Golang使用WaitGroup的一點隨想


前言(為什么又要寫一篇隨想文)

上次我寫了一個channel的文章,我尋思,這Golang控制三大巨頭,channel,waitgroup,context,我得盡快都安排上,最近工作太忙,壓力過大,但是Update Blog還是不能夠停下來,所以繼續補上,學習還是不能停,那么來吧。

WaitGroup的簡單用法(等待組)

你品一下人家這名字,等待組。等待什么,等待goroutine完成啊。有些時候,我們啟動多個goroutine去執行任務,我舉個例子

listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"}

for _, ip := range(listip) {
    //假設我們執行一個ping ip 的邏輯
    go PingIPWork(ip)
}

我這里執行了一個多ip去ping的邏輯,一般這種時候,你要是執行一波,人家肯定毛都不會返回給你,為什么?因為人家主線程直接就退出了,還是那句話,你又沒告訴人家主線程要等這ip全部都ping 完,所以你必須要加個等待,等着Goroutine完成,這里我再舉一個網上的例子

package main

import (
    "fmt"
)

func main() {
    go func() {
        fmt.Println("Goroutine 1")
    }()

    go func() {
        fmt.Println("Goroutine 2")
    }()

    //來個睡眠,等Goroutine結束
    time.Sleep(time.Second * 1)
}

看到了么,加了一個sleep,用sleep去等着Goroutine跑完,上面我舉的那個例子也可以這么來

listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"}

for _, ip := range(listip) {
    //假設我們執行一個ping ip 的邏輯
    go PingIPWork(ip)
}

time.Sleep(time.Second * 1)

加個sleep可以等待完成,但是萬一啊,Goroutine有的跑的快,有的慢,你那sleep就一秒,要是有的Goroutine沒跑完不就白瞎了嗎,所以咱們需要一個機制,這個機制可以幫助咱們去管理Goroutine,讓我們知道Goroutine這東西什么時候停,什么時候完成。所以,WaitGroup這個東西,就可以幫助我們解決這個問題,還是老樣子,我舉一個簡單的例子來說明我的想法。

package main

import (
    "fmt"
	"sync"
)


func PingIPWork(ip string) {
	fmt.Println(ip)
}


func main() {

    //定義一個等待阿祖
	var wg sync.WaitGroup


	wg.Add(3) // 因為有3個Ip,咱們定義三個動作,所以來三個計數

	listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"}

	for _, ip := range(listip) {
		//假設我們執行一個ping ip 的邏輯
		go func(ip string) {
            //執行一個work
            PingIPWork(ip)
            //操作完成之后,done一個計數,也就是3-1
			wg.Done()
		}(ip)
 }
    //等待
	wg.Wait() // 等待,直到計數為0
}

這里我舉了一個簡單的例子,其實wg的用法較為簡單,在這個例子里面我們用到了

wg.wait
等待Goroutine結束之后退出主進程

wg.Add
添加Goroutine,其實你可以把它想成,可添加的最大Goroutine數

wg.Done
想象成銷毀參數,當Goroutine結束之后調用,意思就是,你沒了,我減1

WaitGroup的其他注意事項

將Wg作為參數進行傳遞的時候,需要使用指針

有些時候,咱們不想寫的這么麻煩,就尋思怎么才能簡單一點,或者可變性稍微強一點,有些時候我們要把wg最為參數,在函數內部調用,我們該怎么寫呢?

package main

import (
	"fmt"
	"sync"
)


func PingIPWork(ip string, wg *sync.WaitGroup) {
	fmt.Println(ip)
	wg.Done()
}


func main() {

	var wg sync.WaitGroup


	wg.Add(3) // 因為有兩個動作,所以增加2個計數

	listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"}

	for _, ip := range(listip) {
		//假設我們執行一個ping ip 的邏輯
		go PingIPWork(ip, &wg)
		}

	wg.Wait() // 等待,直到計數為0
}

看到了么,如果你把Wg作為參數進行傳遞,你得要用指針的形式傳值,否則就會死鎖!!!!!!!!

Wg.Add的數值不能為負

wg.Add()的數值必須為正數,如果為負數,將會拋出異常。

panic: sync: negative WaitGroup counter

goroutine 1 [running]:
sync.(*WaitGroup).Add(0xc042008230, 0xffffffffffffff9c)
    D:/Go/src/sync/waitgroup.go:75 +0x1d0
main.main()
    D:/code/go/src/test-src/2-Package/sync/waitgroup/main.go:10 +0x54


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM