单向通道模式
常见的单向通道设计模式
单向通道为 goroutine 之间的受控通信提供了强大的机制,使并发编程更具可预测性和安全性。
管道模式
graph LR
A[输入] --> B[阶段 1]
B --> C[阶段 2]
C --> D[输出]
实现示例
func generateNumbers(max int) <-chan int {
ch := make(chan int)
go func() {
for i := 1; i <= max; i++ {
ch <- i
}
close(ch)
}()
return ch
}
func squareNumbers(input <-chan int) <-chan int {
output := make(chan int)
go func() {
for num := range input {
output <- num * num
}
close(output)
}()
return output
}
func main() {
numbers := generateNumbers(5)
squared := squareNumbers(numbers)
for result := range squared {
fmt.Println(result)
}
}
扇出模式
graph LR
A[单个通道] --> B[工作线程 1]
A --> C[工作线程 2]
A --> D[工作线程 3]
实现示例
func fanOutWorker(id int, jobs <-chan int, results chan<- int) {
for job := range jobs {
result := job * 2
results <- result
}
}
func fanOutProcess(jobCount int) {
jobs := make(chan int, jobCount)
results := make(chan int, jobCount)
// 启动工作线程
for w := 1; w <= 3; w++ {
go fanOutWorker(w, jobs, results)
}
// 发送任务
for j := 1; j <= jobCount; j++ {
jobs <- j
}
close(jobs)
// 收集结果
for a := 1; a <= jobCount; a++ {
<-results
}
}
工作池模式
模式组件 |
描述 |
输入通道 |
接收任务 |
工作线程通道 |
并发处理任务 |
结果通道 |
收集处理后的结果 |
实现示例
func worker(id int, jobs <-chan int, results chan<- int) {
for job := range jobs {
fmt.Printf("工作线程 %d 正在处理任务 %d\n", id, job)
results <- job * 2
}
}
func workerPool(jobCount, workerCount int) {
jobs := make(chan int, jobCount)
results := make(chan int, jobCount)
// 创建工作池
for w := 1; w <= workerCount; w++ {
go worker(w, jobs, results)
}
// 发送任务
for j := 1; j <= jobCount; j++ {
jobs <- j
}
close(jobs)
// 收集结果
for a := 1; a <= jobCount; a++ {
<-results
}
}
最佳实践
- 使用只发送和只接收的通道方向
- 当不再发送数据时关闭通道
- 实现适当的错误处理
- 考虑使用带缓冲的通道进行性能优化
在 LabEx,我们强调使用单向通道来创建更具可预测性和可维护性的并发 Go 应用程序。