使用waitgroup在循环中开Goroutine处理并发任务
简介
实际项目中遇到了需要并发处理的任务,在for循环中用Go的Goroutine去处理任务遇到了一些问题,这里写一个demo记录一下简单的过程。
同步的代码
这里用一个简单的time.sleep模拟一下同步的代码,然后再看看开协程处理的不同之处:
package main import ( "fmt" "time" ) func main() { // 同步代码 lst := []int8{1,2,3} start := time.Now() for _,i := range lst{ DeltaTask(i) } end := time.Now() ret := end.Sub(start) fmt.Printf("耗时:%v",ret) } // 模仿耗时的任务 func DeltaTask(i int8){ time.Sleep(time.Duration(i)*time.Second) } // 耗时:6.008863168s
开协裎的写法
这里直接上代码:
package main import ( "fmt" "sync" "time" ) func main() { // 异步代码 lst := []int8{1,2,3} start := time.Now() // 定义一个waitgroup wait := sync.WaitGroup{} for _,i := range lst{ // tag +1 wait.Add(1) // go一个匿名函数 go func(delta int8){ // tag -1 defer wait.Done() DeltaTask(delta) }(i) } // 主线程等待 "计时器" 为0才往下走直到停止 wait.Wait() end := time.Now() ret := end.Sub(start) fmt.Printf("耗时:%v",ret) } // 模仿耗时的任务 func DeltaTask(i int8){ time.Sleep(time.Duration(i)*time.Second) } // 耗时:3.005254124s
这里最重要的就是WaitGroup的使用!可以跟Python并发编程中的join方法进行类比:因为在Go中主线程结束后意味着主线程中开的协裎也都挂了,所以一定要确保执行协裎任务时主线程一直处于wait的状态!