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

Go语言中使用带channel的select语句时程序为何阻塞?

问题根因
  • 通道初始化顺序错误:你在启动goroutine go a.f()之后才对a.exit做初始化操作,如果goroutine调度速度快于main的初始化逻辑,select判断时a.exit还是nil通道,读取nil通道会永远阻塞,程序直接死锁,甚至连-----over-----都无法输出,当前能输出是调度顺序巧合,逻辑不稳定。
  • 无缓冲通道双向写入无接收方导致阻塞:a.exit是无缓冲通道,main向通道写入true后,f的goroutine成功读取到信号输出-----over-----,接下来你在f中再次向a.exit写入true,此时没有任何其他goroutine在监听该通道的读取操作,无缓冲通道的写入操作会永久阻塞,因此无法执行后续的打印语句。
修复方案

如果需要实现「main发退出信号 + 子goroutine返回退出确认」的逻辑,可以提前初始化带缓冲的通道,同时main等待确认信号即可,修复后的代码如下:

package main

import (
	"fmt"
)

type A struct{
	exit chan bool
}

func (a *A) f(){
	select{
	// 业务逻辑的case写在此处
	case <- a.exit:
		fmt.Println("-----over-----")
		// 发送退出确认
		a.exit <- true
		fmt.Println("+++++over++++++")
	}
}

func main() {
	a := A{
		// 初始化带1个缓冲的通道,避免写入时无接收方阻塞
		exit: make(chan bool, 1),
	}
	// 通道初始化完成后再启动goroutine,避免读取nil通道
	go a.f()
	// 发送退出信号
	a.exit <- true
	// 等待子goroutine的退出确认
	<-a.exit
}

如果是多goroutine的退出通知场景,更推荐直接使用标准库的context.Context实现,支持级联取消、超时控制,不需要手动维护多个通道。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:45:03