Go中如何在Goroutine向Channel发数据时避免程序无限运行?
解决方案
你的核心问题是两个:一是要实现发送goroutine向channel边发送边被接收,而非等待所有发送完成才开始接收;二是不受控的长期goroutine会阻止程序自动退出,需要在处理完所有数据后主动终止程序。
修改思路
- 不要在
someFunc中直接阻塞等待所有发送goroutine完成,而是启动一个独立的goroutine来执行sync.WaitGroup的等待和channel关闭操作,让someFunc能立即返回channel,实现边发边收。 - 在main函数处理完channel中所有数据后,主动调用
os.Exit(0)强制终止程序,忽略不受控的长期goroutine。
修改后的代码
package main import ( "fmt" "os" "sync" "time" ) func main() { channel := someFunc() // 不受控的长期运行Goroutine go func() { time.Sleep(1000 * time.Hour) }() // 边接收边处理发送过来的数据 for resp := range channel { fmt.Println(resp) } // 所有数据处理完成,主动终止程序 os.Exit(0) } func someFunc() chan int { var wg sync.WaitGroup t := make(chan int, 10) arr := []int{1, 2, 3, 4, 5, 6, 7, 8} for _, i := range arr { wg.Add(1) go func(i int) { defer wg.Done() time.Sleep(time.Duration(i) * time.Second) t <- i }(i) } // 启动独立Goroutine等待所有发送完成后关闭channel go func() { wg.Wait() close(t) }() return t }
关键说明
- 独立的等待goroutine:将
wg.Wait()和close(t)放到单独的goroutine中,someFunc可以立即返回channel,main函数就能马上开始接收数据,实现并发发送和接收。 - 主动终止程序:当channel被关闭且所有数据被接收后,
for range循环会退出,此时调用os.Exit(0)可以直接终止整个进程,不受那个长期运行的goroutine影响。
内容的提问来源于stack exchange,提问作者Brandon Kauffman
相关产品推荐
相关产品推荐

