不同于Channel。Channel可以帮助我们很好的控制并发,但是开发习惯和表现出来的表达不太一样,所以在Go语言中,可以使用sync包中的WaitGroup来实现并发控制,更直观。基本使用示例我们修改前面的例子,引入sync.WaitGroup来实现并发控制。?首先,我们在主函数中定义WaitGroupvarwgsync.WaitGroup。每次执行任务时,都会调用Add()方法wg.Add(1)。在main函数中,我们使用Wait()方法等待并发结束wg.Wait()?在调用函数中,我们需要将WaitGroup作为指针传入,否则会导致死锁//mainfunctiongoready(5,&wg)//functionfuncready(sint,wg*sync.WaitGroup)同时函数执行完后,调用wg.Done,我们使用defer实现deferwg.Done()完整代码packagemainimport("fmt""sync""time")funcready(sint,wg*sync.WaitGroup){deferwg.Done()fmt.Printf("在goroutine中运行func并等待%v\n",s)time.Sleep(time.Second*time.Duration(s))fmt.Printf("在goroutine中运行func并等待%v结束\n",s)}funcmain(){varwgsync.WaitGroupwg.Add(1)goready(5,&wg)mainWaitSec:=2fmt.Printf("运行Main函数并等待%v\n",mainWaitSec)time.Sleep(time.Second*time.Duration(mainWaitSec)))fmt.Printf("RunMainfunctionandwaitfor%vdone\n",mainWaitSec)wg.Wait()}特别提醒的是当WaitGroup传给the函数,需要以指针的形式传递,否则会造成多任务死锁。例子如果不想在函数中传递WaitGroup,也可以使用下面的方法,通过并发匿名函数,在主函数Concurrency的逻辑中进行精准控制varwgsync.WaitGroupfori:=0;我<5;i++{wg.Add(1)waitSec:=i+1gofunc(){deferwg.Done()ready(waitSec)}()}完整代码packagemainimport("fmt""sync""time")funcready(sint){fmt.Printf("在goroutine中运行func并等待%v\n",s)time.Sleep(time.Second*time.Duration(s))fmt.Printf("在goroutine中运行funcgoroutine并等待%vend\n",s)}funcmain(){varwgsync.WaitGroupfori:=0;我<5;i++{wg.Add(1)waitSec:=i+1gofunc(){deferwg.Done()ready(waitSec)}()}mainWaitSec:=2fmt.Printf("运行Main函数并等待%v\n",mainWaitSec)time.Sleep(time.Second*time.Duration(mainWaitSec))fmt.Printf("运行Main函数并等待%v完成\n",mainWaitSec)wg.Wait()}运行结果如下运行Main函数并等待goroutine中的2Runfunc并等待goroutine中的2Runfunc并等待goroutine中的4Runfunc并等待goroutine中的5Runfunc并等待goroutine中的1Runfunc并等待goroutine中的3Runfunc并等待1endRunMain函数并等待goroutine中的2doneRunfunc并等待对于goroutine中的2endRunfunc并等待goroutine中的3endRunfunc并等待goroutine中的4endRunfunc并等待5end
