Go HTTP服务器测试并发Rest API时挂起,通道使用异常
问题分析与解决方案
原代码的核心问题
第一个版本里,你用了无缓冲通道chalk,四个协程往通道发送数据,主协程用for range遍历通道接收数据。但for range遍历通道的逻辑是一直等待直到通道被关闭,你没关闭通道,所以主协程会卡在循环里,永远到不了w.Write那行,自然无法返回HTTP响应。
第二个版本的错误更明显:你把close(chalk)和wg.Wait()放在了for range循环之后,但主协程根本走不到这两行——因为for range还在等着通道关闭,直接造成死锁。另外,wg.Wait()应该等所有工作协程都写完数据后,再关闭通道,这样主协程的循环才能正常退出。
正确的修改代码
func concurrent2(w http.ResponseWriter, r *http.Request) { chalk := make(chan string) var wg sync.WaitGroup for i := 0; i < 4; i++ { wg.Add(1) go func() { defer wg.Done() log.Print("=>") chalk <- "Hello" }() } // 启动单独协程等待所有工作协程完成,然后关闭通道 go func() { wg.Wait() close(chalk) }() fmt.Println("out Of the Loop") var message string for value := range chalk { message += value log.Print("Value 2 ", message) } // 循环退出说明通道已关闭,所有数据都接收完成 w.Write([]byte(message)) }
关键改动说明
- 新增一个匿名协程,专门负责等待所有工作协程执行完毕(
wg.Wait()),然后关闭通道chalk。 - 主协程的
for range循环会在通道关闭后自动退出,之后就能正常执行w.Write返回响应了。 - 无缓冲通道在这里可以正常工作:每个工作协程发送数据时,会阻塞到主协程接收数据,不会出现数据丢失的情况。
内容的提问来源于stack exchange,提问作者Ankit Chakraborty
相关产品推荐
相关产品推荐

