在你提供的 Go 代码中,程序会出现死锁(或“阻塞”)的问题。让我们逐步分析一下这个代码:
创建通道和 WaitGroup:
chanT := make(chan int) wg := sync.WaitGroup{}
启动一个 goroutine 来发送数据:
go func() { wg.Add(1) defer wg.Done() for i := 0; i < 100; i++ { chanT <- i } }()
在这个 goroutine 中,你使用
chanT
通道向其发送了 100 个整数。接收数据:
for task := range chanT { fmt.Println(task) } close(chanT) wg.Wait()
在这里,你有两个主要问题:
问题一:未关闭通道
- 在主函数中,你尝试从
chanT
通道中读取数据,但你没有正确地关闭通道。由于没有关闭通道,for range
循环将会一直等待,直到通道被关闭,因此导致了死锁。
正确的做法:
为了避免死锁并确保正常运行,可以将 close(chanT)
移到 goroutine 完成后,并且在 wg.Wait()
后再调用它。以下是修复后的代码示例:
package main
import (
"fmt"
"sync"
)
func main() {
chanT := make(chan int)
wg := sync.WaitGroup{}
go func() {
wg.Add(1)
defer wg.Done()
for i := 0; i < 100; i++ {
chanT <- i
}
}()
go func() {
wg.Wait() // 等待发送 goroutine 完成后关闭通道
close(chanT) // 一旦所有任务完成,关闭通道
}()
for task := range chanT {
fmt.Println(task)
}
}
总结
- 使用
sync.WaitGroup
的好处是可以确保在执行完所有任务后才关闭通道,这样可以避免因提前关闭通道而导致的 panic。 - 确保合理安排并发任务的生命周期,以有效利用 Go 的并发特性。
内容由零声教学AI助手提供,问题来源于学员提问