Go语言channel数据推送成功但接收goroutine未读取问题求解
问题原因
你遇到的问题是两个值拷贝操作导致的,和嵌套goroutine没有关系:
RegisterWithBufferService方法使用了值接收器而非指针接收器
你定义的方法签名是func (s ServiceA) RegisterWithBufferService(bufService *DataBuffer) error,Go调用值接收器方法时会拷贝一份调用者对象,方法内部对s.IncomingBuffChan、s.OutgoingBuffChans的所有修改都只作用在临时副本上,原始的ServiceA实例属性不会有任何变化。- main函数中存入
BufferedServices数组的是ServiceA的值副本
你执行BufferedServices = append(BufferedServices, *serviceA)时,把serviceA指针指向的对象做了值拷贝存入数组,后续遍历数组调用注册方法时,操作的是数组里的独立副本,和你用来启动录制、发送数据的原始serviceA实例完全无关。
两者叠加后,你实际用来发数据的serviceA实例的OutgoingBuffChans属性始终是空切片,record方法里的for循环遍历空切片不会执行任何发送操作,自然Service B的监听goroutine永远收不到数据。你看到的Data sent.日志只是for循环结束后的固定输出,和是否真的发送了数据没有关系。
修复方案
- 将
ServiceA的两个接口实现方法的接收器改为指针类型:
// 指针接收器,修改会作用到原始实例 func (s *ServiceA) RegisterWithBufferService(bufService *DataBuffer) error { // 原有逻辑不变 } func (s *ServiceA) ServiceName() string { return s.name }
- main函数中向
BufferedServices数组存入指针,不要做值拷贝:
// 存入指针而非解引用后的值 BufferedServices = append(BufferedServices, serviceA)
额外可优化点
你当前buffer逻辑的触发条件是len(buf) > bufferPeriod,默认defaultBufferingPeriod=3,需要收到第4条数据才会回传结果,如果希望满3条就触发回传,可以把判断条件改为len(buf) >= bufferPeriod。
内容的提问来源于stack exchange,提问作者Paul Côté
相关产品推荐
相关产品推荐

