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

Go语言通道传数据异常求助:为何数据无法抵达fmt.Println?

问题分析与解决方案

你的代码有几个关键问题导致数据无法传递到fmt.Println(<-c),咱们一个个拆解:

1. 无限循环让后续代码永远没机会执行

main函数里的for { ... }是个没有退出条件的死循环,它会一直霸占程序执行流,后面的fmt.Println(<-c)语句根本不可能被运行到——不管前面的逻辑有没有问题,这行代码都永远触达不了。

2. 无缓冲通道的发送阻塞,引发WaitGroup死锁

你创建的是无缓冲通道c := make(chan string),这类通道的发送操作c <- "test"必须等到有接收方准备好接收数据时,才能完成并往下执行。而你的代码逻辑里:

  • Avg goroutine启动后,立刻卡在c <- "test"上,等着有人来收数据
  • main goroutine则卡在wg.Wait()上,等着Avg执行完defer wg.Done()
    两边互相等,直接形成死锁,程序第一次触发定时器后就彻底卡住了。

修复后的示例代码

这里给你调整了两种可行的修复方案:

方案一:保留WaitGroup,新增接收goroutine

package main

import (
	"fmt"
	"sync"
	"time"
)

func Avg(c chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	c <- "test"
}

func main() {
	var wg sync.WaitGroup
	c := make(chan string)
	timer1 := time.NewTicker(5 * time.Second)
	
	// 只执行一次定时器触发,去掉无限循环
	select {
	case <-timer1.C:
		wg.Add(1)
		go Avg(c, &wg)
		// 单独开goroutine接收数据,避免发送阻塞
		go func() {
			fmt.Println(<-c)
		}()
		wg.Wait()
	}
	timer1.Stop()
}

方案二:用通道替代WaitGroup做同步(更简洁)

package main

import (
	"fmt"
	"time"
)

func Avg(c chan string) {
	c <- "test"
}

func main() {
	c := make(chan string)
	timer1 := time.NewTicker(5 * time.Second)
	
	<-timer1.C
	go Avg(c)
	fmt.Println(<-c) // 直接接收通道数据,利用通道本身的同步特性
	timer1.Stop()
}

关键总结

  • 无缓冲通道的发送和接收必须同时就绪,否则会阻塞;如果需要异步发送,可以考虑用带缓冲的通道(比如make(chan string, 1))
  • 避免无意义的无限循环,确保后续代码有执行机会
  • 用WaitGroup配合通道时,要注意避免因通道阻塞导致的WaitGroup无法完成的死锁情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:41:06