Golang中死锁错误问题的解决方法

Golang中死锁错误问题的解决方法 链接 我正在向我的 channel 中放入数据,并从不同的 goroutine 中取出。 在我从 channel 中取出所有需要的数据后,我遇到了死锁错误。 使用普通的 for 循环 像下面这样:

for i := 0; i < *n; i++ {
  	res := <-c
  	fmt.Printf("[%s  %v]\n", res.label, res.time.Format("15: 04: 05.0000"))
  }

可以正常工作,但我需要使用 range 来处理它。

知道代码有什么问题吗? 我认为问题在于找到在哪里关闭我的 channel。 链接


更多关于Golang中死锁错误问题的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

非常感谢。我自己可能无法解决这个问题。

更多关于Golang中死锁错误问题的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,这很常见。你可以在单独的 goroutine 中等待并关闭通道:

	go func() {
		wg.Wait()
		close(c)
	}()
	consumer(c)

问题在于你没有正确关闭 channel,导致 range 循环无法知道何时停止接收数据。range 会一直尝试从 channel 读取,直到 channel 被显式关闭。

在你的代码中,worker goroutine 发送完所有数据后没有关闭 channel,因此主 goroutine 中的 range c 会一直等待更多数据,造成死锁。

这是修复后的示例:

package main

import (
	"fmt"
	"time"
)

type result struct {
	label string
	time  time.Time
}

func worker(c chan<- result, n int) {
	defer close(c) // 关键:发送完成后关闭 channel
	for i := 0; i < n; i++ {
		c <- result{
			label: fmt.Sprintf("worker %d", i),
			time:  time.Now(),
		}
	}
}

func main() {
	c := make(chan result)
	n := 5

	go worker(c, n)

	// 使用 range 安全地接收所有数据
	for res := range c {
		fmt.Printf("[%s  %v]\n", res.label, res.time.Format("15:04:05.0000"))
	}
}

关键修改:

  1. worker 函数中使用 defer close(c),确保函数退出时关闭 channel
  2. 发送方负责关闭 channel,而不是接收方
  3. range c 会在 channel 关闭后自动退出循环

这样修改后,range 循环会在所有数据接收完毕后正常退出,避免了死锁。

回到顶部