Golang channel 注意事项
在 Go 中,可以使用 channel 实现限流,即通过 channel 的容量控制并发执行的协程数。
示例代码如下:
```go
package main
import (
"fmt"
"time"
)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("worker %d 执行任务 %d\n", id, j)
time.Sleep(time.Second) // 模拟任务执行时间
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100) // 创建任务 channel,缓冲区大小为 100
results := make(chan int, 100) // 创建结果 channel,缓冲区大小为 100
// 创建 3 个 worker 协程,即最多同时执行 3 个任务
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// 发送 9 个任务到 jobs channel
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs) // 关闭 jobs channel,表示所有任务已发送完毕
// 收集所有结果
for a := 1; a <= 9; a++ {
<-results
}
}
```
在上面的示例中,我们创建了一个 `jobs` channel 和一个 `results` channel,用于分别传递任务和结果。我们创建了 3 个 worker 协程,并将 `jobs` 和 `results` channel 分别传递给它们。在主协程中,我们向 `jobs` channel 发送 9 个任务,并关闭 `jobs` channel,表示所有任务已发送完毕。然后我们收集所有结果。
由于 `jobs` channel 的缓冲区大小为 100,即最多可以存储 100 个任务,而 `results` channel 的缓冲区也为 100,即最多可以存储 100 个结果。因此,当 worker 协程数小于等于 3 时,所有任务都可以立即执行;当 worker 协程数大于 3 时,多余的任务会被存储在 `jobs` channel 中,直到有空闲的 worker 协程可以执行它们。这样就实现了限流的功能。