跳到主要内容

go-协程

可以理解goroutine协程就是创建多个并发执行的任务 goroutine协程 = 实现并发的一种方式

  • 协程(goroutine)
    • 可以让多个任务并发执行,比如一边查订单、一边发短信、一边写日志,每个程序执行之间不互相堵塞
  • 通过go关键字来启动一个goroutine协程
    • 用 go 启动协程,可以用来创建并发任务
  • 协程之间怎么传数据,主要靠 channel
  • 多个协程要「等它们都做完」,常用 sync.WaitGroup

协程和并发注意问题​

  • 并发不一定等于真正“同一时刻并行执行”
  • WaitGroup使用问题,Add 在启动协程之前调用;Done 在协程内部调用。

创建多个并发任务​

  • 创建多个goroutine协程 = 创建多个并发任务
  • 注意goroutine 是并发执行,创建了多个,就同时并发执行
go
go queryOrder()
go sendSMS()
go writeLog()

WaitGroup​

通过WaitGroup来等待这些并发任务的执行

  • goroutine 负责并发执行任务,WaitGroup 负责等这些并发任务全部结束

WaitGroup 三个核心方法​

  • wg.Add(n): 表示有 n 个任务需要等待,计数器加1
  • wg.Done():一个任务执行完成,计时器减1
  • wg.Wait():等待并发任务,直到计数器变为 0
go
wg.Add()
wg.Done()
wg.Wait()

协程并发任务例子​

go
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("全部通知完成")
}