假设有一组任务有前后依赖关系,我们可以使用Go的通道特性,将前一个任务的执行结果(或结束信号)送入下一个任务,已达到自动化依次执行工作流的每个任务的目的。
为了模拟这一工作流,我们假设有五个通道和四个协程,每个协程监听前一个通道的数据,并将接收到的数据送入下一个通道中。
当任务执行结束后,最好能够主动回收通道,已达到节省内存开销的目的。与执行工作流类似的是,应当能做到关闭首个通道后,按照依赖关系连锁关闭后续所有通道。
示例代码如下:https://go.dev/play/p/zcuEA7t_zSU
package main
import (
"fmt"
"time"
)
func main() {
// 创建通道
channels := make([]chan int, 5)
for i := range channels {
channels[i] = make(chan int)
}
// 设置协程
for i := 0; i < len(channels)-1; i++ {
i := i
go func(in <-chan int, out chan<- int) {
for {
value, ok := <-in // 从前一个通道接收数据
if !ok {
fmt.Printf("Channel[%d] closed. Exiting goroutine.\n", i)
close(out)
return
}
out <- value // 发送数据到下一个通道
}
}(channels[i], channels[i+1])
}
// 启动第一个协程,将数据发送到第一个通道
go func(out chan<- int) {
for i := 0; i < 10; i++ {
out <- i // 发送数据到第一个通道
}
close(out) // 关闭第一个通道
}(channels[0])
// 从最后一个通道接收数据并打印
for {
select {
case value, ok := <-channels[len(channels)-1]:
if !ok {
fmt.Println("Last channel closed. Exiting.")
return
}
fmt.Println("Received:", value)
case <-time.After(1 * time.Second):
fmt.Println("Timeout. Exiting.")
return
}
}
}
执行结果如下:
Received: 0
Received: 1
Received: 2
Received: 3
Received: 4
Received: 5
Received: 6
Received: 7
Channel[0] closed. Exiting goroutine.
Channel[1] closed. Exiting goroutine.
Channel[2] closed. Exiting goroutine.
Received: 8
Received: 9
Channel[3] closed. Exiting goroutine.
Last channel closed. Exiting.
从执行结果中可以看出,最后一个协程的结果还未送出时,首个通道既已开始关闭。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。