网站网页设计项目计划书,南城网络公司,工作不顺心压抑想辞职,做脚垫版型的网站在后端开发当中#xff0c;经常会遇到这样的场景#xff1a;请求给了批量的输入#xff0c;对于每一个输入#xff0c;我们都要给外部发请求等待返回#xff0c;然后才能继续其它自己的业务逻辑。在这样的case下#xff0c;如果每一个输入串行处理的话#xff0c;那么很…在后端开发当中经常会遇到这样的场景请求给了批量的输入对于每一个输入我们都要给外部发请求等待返回然后才能继续其它自己的业务逻辑。在这样的case下如果每一个输入串行处理的话那么很大一部分时间都会损耗在给外部发请求这个环节因此我们会希望把这些请求放到各个goroutine里异步执行等待批量执行完成之后再继续后面的逻辑。这个时候我们就可以用到这个东西sync.WaitGroup
WaitGroup提供了增减计数以及阻塞等待计数归零的线程安全接口。当主goroutine增加计数并等待的时候子goroutine的逻辑中若引用了一个WaitGroup实例的话也可以在结束defer的时候去减少计数这样当主goroutine自旋等待计数归零时等待的逻辑就返回了就继续后面的内容。整体上就达到了等待多路并行的异步任务这一效果。
一个典型的代码案例如下 func TestWaitGroup(t *testing.T) {var wg sync.WaitGroupstartTime : time.Now()for i : 0; i 5; i {n : i 1sleepTime : time.Duration(n) * time.Secondwg.Add(1)go func() {defer wg.Done()t.Logf(task %d started, n)time.Sleep(sleepTime)t.Logf(task %d ended, n)}()}t.Logf(waiting for all tasks done...)wg.Wait()endTime : time.Now()t.Logf(all tasks done! elapsed time: %v, endTime.Sub(startTime))
}整个逻辑很简单我们起了5个任务每个任务分别sleep上1到5秒。主goroutine此时在每个任务开始前给WaitGroup实例wg加上1个计数而在子goroutine里defer地调用wg.Done减少计数。主goroutine起完任务之后直接调用wg.Wait自选等待。这样5s后等所有任务Done主goroutine就会接下来打印消耗时间的日志信息了。
打印的内容如下 RUN TestWaitGroupwg_test.go:26: waiting for all tasks done...wg_test.go:21: task 5 startedwg_test.go:21: task 1 startedwg_test.go:21: task 2 startedwg_test.go:21: task 3 startedwg_test.go:21: task 4 startedwg_test.go:23: task 1 endedwg_test.go:23: task 2 endedwg_test.go:23: task 3 endedwg_test.go:23: task 4 endedwg_test.go:23: task 5 endedwg_test.go:29: all tasks done! elapsed time: 5.0015089s
--- PASS: TestWaitGroup (5.00s)
PASSWaitGroup的用法非常简单但这里注意的是实际遇到这种编程场景一般会涉及到多任务运行结果收集还有程序异常处理相关的内容。因此像recover或者select超时等一些子goroutine任务异常处理的逻辑可能视实际情况都得配合加上。