Go并发编程实现多函数并行报send on closed channel错误求助
Go并发终端程序panic问题修复
问题根因
你的代码触发send on closed channel panic有三个核心错误:
- main函数里过早关闭通道:启动3个goroutine后立刻执行了
close(inChan),此时goroutine刚启动还在运行,后续getInputs往已经关闭的通道写数据直接触发panic。 - 通道使用逻辑错误:你用同一个无缓冲通道同时给
showTime和showInputs传值,无缓冲通道的消息只会被其中一个消费者随机取走,会出现时间打印和输入响应互相抢消息的问题。 - 定时逻辑不符合需求:
showTime现有逻辑是等通道消息才打印时间、睡一秒,根本做不到每秒自动打印时间的设计目标——你之前看到的连续3秒打印时间,本质是从已关闭通道读取零值触发的循环,不是正常的定时逻辑。
修复思路
- 把打印时间的逻辑改成独立的ticker定时触发,不需要依赖输入通道传值,用独立的退出信号控制它终止
- 不要在main里提前关通道,等所有逻辑跑完(收到done信号)再做资源回收
- 输入通道只负责传递用户输入内容,单独开goroutine处理输入响应,和定时打印时间逻辑完全解耦
- 用独立的
done通道做全局退出广播,收到"done"输入时通知所有goroutine退出,再等待所有goroutine收尾后退出程序
修正后可运行代码
package main import ( "bufio" "fmt" "os" "sync" "time" ) // getInputs 监听用户输入,非空内容写入输入通道 func getInputs(ch chan<- string, wg *sync.WaitGroup) { defer wg.Done() scanner := bufio.NewScanner(os.Stdin) for { // 逐行读取用户输入,比Scanln更稳定,支持带空格的输入 if !scanner.Scan() { break } input := scanner.Text() if input != "" { ch <- input // 收到done指令就退出输入监听 if input == "done" { return } } } } // showInputs 处理用户输入的指令响应 func showInputs(inCh <-chan string, done chan<- struct{}, wg *sync.WaitGroup) { defer wg.Done() for { msg := <-inCh switch msg { case "dog": fmt.Println("YEP thats a dog!") case "done": // 收到done信号,通知所有协程退出 close(done) return default: fmt.Printf("Received your input: %s\n", msg) } } } // showTime 每秒打印当前时间,收到退出信号就终止 func showTime(done <-chan struct{}, wg *sync.WaitGroup) { defer wg.Done() // 初始化每秒触发的ticker ticker := time.NewTicker(time.Second) defer ticker.Stop() // 启动后立刻打印一次当前时间 fmt.Println(time.Now().String()) for { select { case <-ticker.C: fmt.Println(time.Now().String()) case <-done: return } } } func main() { var wg sync.WaitGroup inChan := make(chan string) done := make(chan struct{}) // 全局退出信号通道 wg.Add(3) go showTime(done, &wg) go showInputs(inChan, done, &wg) go getInputs(inChan, &wg) // 等待所有协程收尾 wg.Wait() fmt.Println("The End!") }
代码运行说明
- 程序启动后会立刻打印当前时间,之后每秒自动刷新打印时间
- 输入任意文本回车,程序会回显收到的输入;输入
dog会触发固定响应YEP thats a dog! - 输入
done回车后,所有运行中的goroutine会收到退出信号,完成收尾后打印The End!正常退出,不会触发panic
内容的提问来源于stack exchange,提问作者Kiarash Salooti
相关产品推荐
相关产品推荐

