Go语言带延迟拷贝io.Reader到io.Writer空写入问题求助
问题根因
- 第一个错误是
MyReader的Read实现违反了io.Reader接口的约定:
调用方传入的p []byte是预先分配好的缓冲区,用于存储读取到的数据。你代码中直接给局部变量p赋值p = []byte(someString),只是修改了局部变量的指针指向,完全没有修改调用方传入的缓冲区内容,导致上层拿到的数据始终为空。 - 第二个错误是使用
bufio.Writer时没有调用Flush():
带缓冲的写入会先把数据存在内部缓冲区,只有缓冲区满或者主动调用Flush时,才会把数据真正写入底层的MyWriter,所以你后面3种方案看不到MyWriter.Write被执行。
修复方案
1. 修正MyReader的Read实现
将内容拷贝到传入的缓冲区中,而不是直接修改切片指针:
func (r *MyReader) Read(p []byte) (read int, err error) { someString := fmt.Sprintf("testing-%d", rand.Int()) // 把生成的字符串拷贝到调用方提供的缓冲区p中 read = copy(p, someString) log.Printf("io read %d bytes: %s\n", read, string(p[:read])) return read, io.EOF }
2. 修正bufio.Writer的使用
所有调用bufWrite.Write的位置,写完之后必须调用bufWrite.Flush()把缓冲区数据刷入底层写入器:
比如在ReadBytesApproach中:
wrote, err := bufWrite.Write(readBytes) if err != nil { log.Printf("error writing: %s\n", err) } // 加这行刷新缓冲区 bufWrite.Flush()
3. 可控拷贝的最简实现
如果你不需要bufio的能力,完全可以自己控制读写流程,更灵活:
func CustomCopy() { reader := MyReader{} writer := MyWriter{} // 自定义缓冲区大小 buf := make([]byte, 4096) for { n, err := reader.Read(buf) if n > 0 { // 此处可插入你需要的Read/Write之间的自定义逻辑 _, writeErr := writer.Write(buf[:n]) if writeErr != nil { log.Printf("写入失败: %v", writeErr) break } } if err == io.EOF { // 读取完成,按需决定是否退出循环 break } if err != nil { log.Printf("读取失败: %v", err) break } time.Sleep(1 * time.Second) } }
内容的提问来源于stack exchange,提问作者James Cathcart
相关产品推荐
相关产品推荐

