
本文详解如何通过 goroutine 和 channel 正确实现从 os.Stdin 实时读取并立即写入 os.Stdout,避免因通道操作顺序不当导致的延迟输出或死锁问题。
本文详解如何通过 goroutine 和 channel 正确实现从 os.stdin 实时读取并立即写入 os.stdout,避免因通道操作顺序不当导致的延迟输出或死锁问题。
在 Go 中,利用 channel 进行 I/O 流的解耦与异步处理是常见模式,但初学者常因对 select 语义和 channel 缓冲机制理解不足而陷入阻塞陷阱。原代码的核心问题在于:
(从 ch 接收值),再尝试将该值发送至 mes。由于 mes 是带缓冲的 chan message(容量为 1),且 select 仅保护“外层”发送操作是否就绪, 本身仍会阻塞,直到 read() goroutine 发送第二个消息,从而造成输出延迟(即输入第二行后才打印第一行)。
-
永远优先用
scanner.Text():scanner.Bytes()返回的切片指向内部缓冲区,下一次Scan()会覆盖其内容,导致数据错乱。 -
显式错误处理:生产环境应在
read()goroutine 中检查scanner.Err()并记录/传播错误。 -
避免无缓冲 channel 的双向依赖:如
mes无缓冲,且主循环与转发 goroutine 相互等待,极易引发死锁。 -
及时关闭 channel:使用
close()通知消费者数据流结束,使range循环自然退出。
通过以上任一方案,即可实现预期行为:每输入一行(回车后),立即输出两行日志("Message to channel 2" 和 "Message to stdout")及对应内容,真正达成低延迟、可组合的流式 I/O 处理。










