You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Go语言通道死锁?排查程序通道阻塞位置

问题分析与修复

阻塞原因

  1. 重复接收通道值:calculator函数的select分支中,比如case <-secondChan后又执行returnChan <- (<-secondChan) *3,这要求从secondChan接收两次值,但main里只发送了一次2,第二次接收会永久阻塞,导致returnChan无数据返回,最终main中的<-r也跟着阻塞。
  2. 需求实现偏差:原需求是输出第一个通道数字的平方根,但代码里写的是平方运算,不符合要求。
  3. 单次监听限制:当前select仅执行一次就退出,无法持续处理通道的后续输入,不符合持续响应的需求。

修复后的代码

package main

import (
	"fmt"
	"math"
)

func main() {
	ch1, ch2 := make(chan int), make(chan int)
	stop := make(chan struct{})

	r := calculator(ch1, ch2, stop)

	// 测试第二个通道
	ch2 <- 2
	fmt.Println(<-r)

	// 测试第一个通道
	ch1 <- 9
	fmt.Println(<-r)

	// 发送停止信号
	stop <- struct{}{}
}

func calculator(firstChan <-chan int, secondChan <-chan int, stopChan <-chan struct{}) <-chan int {
	returnChan := make(chan int)
	go func() {
		defer close(returnChan)
		for {
			select {
			case num := <-firstChan:
				// 计算平方根,按需处理小数转整数的逻辑
				returnChan <- int(math.Sqrt(float64(num)))
			case num := <-secondChan:
				returnChan <- num * 3
			case <-stopChan:
				return
			}
		}
	}()
	return returnChan
}

关键修复点

  • 避免重复接收:在case分支中直接将通道值接收至变量(num := <-firstChan),一次接收后直接使用变量计算,消除额外阻塞。
  • 循环监听通道:用for包裹select,让goroutine持续监听三个通道的输入,直到收到stop信号才退出。
  • 修正平方根计算:使用math.Sqrt函数实现需求中的平方根功能,处理好整数与浮点数的类型转换。
  • 正确处理stop信号:收到stop信号后直接return,配合defer close(returnChan)关闭返回通道,避免main侧出现不必要的阻塞。

内容的提问来源于stack exchange,提问作者Vadim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 13:45:32