5 回复
我已链接一个格式正确的Go Playground版本
更多关于Golang新手频繁遇到死锁错误问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用Go的数据竞争检测器。
go run -race main.go
我正在尝试从CSV文件中提取患者数据,然后解析数据以找出文件中哪些行包含不完整的患者信息。这是我第一次使用Golang,所以对这门语言还不太熟悉。如果需要关闭通道,请告诉我具体操作方法。感谢您的帮助。
func main() {
fmt.Println("hello world")
}
你的通道是无缓冲的,因此当没有人从中接收消息时,你的goroutine会被阻塞。只需在单独的例程中启动消费函数:
go consume(whichones, counter)
然后发送消息:
msgs <- record[value]
但是,你无法接收比发送数量更多的消息,因此请完全移除消费函数中的循环。
在您提供的代码中,死锁问题主要出现在 main 函数中,原因是没有正确处理 goroutine 的同步和通道的关闭。以下是详细分析和修复后的代码示例。
问题分析
- 通道未关闭:
ch通道在 goroutine 中发送数据后未关闭,导致main函数中的for循环在读取完所有数据后无法退出,从而阻塞并触发死锁。 - 同步机制缺失:
main函数启动 goroutine 后没有等待其完成,直接进入读取循环,可能因 goroutine 未及时发送数据而阻塞。
修复方案
使用 sync.WaitGroup 确保 goroutine 完成,并在发送数据后关闭通道。以下是修改后的代码:
package main
import (
"fmt"
"sync"
)
func main() {
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 5; i++ {
ch <- i
}
close(ch) // 关闭通道以通知接收方无更多数据
}()
// 启动另一个 goroutine 等待发送完成并关闭通道
go func() {
wg.Wait()
}()
// 从通道读取数据,直到通道关闭
for num := range ch {
fmt.Println(num)
}
}
关键点说明
- 使用
sync.WaitGroup:wg.Add(1)表示启动一个 goroutine,defer wg.Done()在 goroutine 结束时减少计数。 - 关闭通道:在发送完所有数据后调用
close(ch),这样for range循环会在通道关闭后自动退出,避免死锁。 - 分离等待逻辑:通过另一个 goroutine 调用
wg.Wait()来等待发送完成,避免阻塞主循环。在实际应用中,如果main函数只需读取数据,可直接在 goroutine 中关闭通道。
运行此代码将输出数字 0 到 4,然后正常退出,无死锁错误。

