go-协程
可以理解goroutine协程就是创建多个并发执行的任务 goroutine协程 = 实现并发的一种方式
- 协程(goroutine)
- 可以让多个任务并发执行,比如一边查订单、一边发短信、一边写日志,每个程序执行之间不互相堵塞
- 通过go关键字来启动一个goroutine协程
- 用 go 启动协程,可以用来创建并发任务
- 协程之间怎么传数据,主要靠
channel - 多个协程要「等它们都做完」,常用
sync.WaitGroup
协程和并发注意问题
- 并发不一定等于真正“同一时刻并行执行”
- WaitGroup使用问题,
Add在启动协程之前调用;Done在协程内部调用。
创建多个并发任务
- 创建多个goroutine协程 = 创建多个并发任务
- 注意
goroutine是并发执行,创建了多个,就同时并发执行
go queryOrder()
go sendSMS()
go writeLog()
WaitGroup
通过WaitGroup来等待这些并发任务的执行
- goroutine 负责并发执行任务,WaitGroup 负责等这些并发任务全部结束
WaitGroup 三个核心方法
- wg.Add(n): 表示有
n个任务需要等待,计数器加1 - wg.Done():一个任务执行完成,计时器减
1 - wg.Wait():等待并发任务,直到计数器变为
0
wg.Add()
wg.Done()
wg.Wait()
协程并发任务例子
package main
import (
"fmt"
"sync"
"time"
)
// 第三个参数接收 WaitGroup 的指针,否则外面读不到 main 里的 wg
func notify(orderID string, cost time.Duration, wg *sync.WaitGroup) {
defer wg.Done() // 这个协程结束时,计数器 -1
time.Sleep(cost) // 仅模拟「发短信 / 调接口」耗时,与「等不等协程」无关
fmt.Println("已通知订单:", orderID)
}
func main() {
var wg sync.WaitGroup // 定义在 main 里:只有 main 和「被传进去的函数」能用它
orders := []struct {
id string
cost time.Duration
}{
{"A1001", 200 * time.Millisecond},
{"A1002", 100 * time.Millisecond},
{"A1003", 150 * time.Millisecond},
}
wg.Add(len(orders)) // 告诉 WaitGroup:一共要等 3 个
for _, o := range orders {
go notify(o.id, o.cost, &wg) // 传地址,不是传副本
}
wg.Wait() // 三个 Done 都调用完才继续
fmt.Println("全部通知完成")
}