我花了几个小时尝试理解底层逻辑,但没有任何进展。下面的代码在第一次迭代后返回死锁。如果我在 io.copy
之前关闭 writer,死锁就会消失,但不会打印任何内容(因为管道写入端在读取之前已关闭)
func main() { reader, writer := io.pipe() c := make(chan string) go func() { for i := 0; i < 5; i++ { text := fmt.sprintf("hello %vth time", i+1) c <- text } close(c) }() for msg := range c { msg = fmt.sprintf("\nreceived from channel -> %v\n", msg) go fmt.fprint(writer, msg) io.copy(os.stdout, reader) writer.close() } }
这是运行代码后的错误
received from channel -> hello 1th time fatal error: all goroutines are asleep - deadlock! goroutine 1 [select]: io.(*pipe).read(0xc000130120, {0xc00013e000, 0x8000, 0xc00011e001?}) /usr/lib/go/src/io/pipe.go:57 +0xb1 io.(*PipeReader).Read(0x0?, {0xc00013e000?, 0xc00011e050?, 0x10?}) /usr/lib/go/src/io/pipe.go:136 +0x25 io.copyBuffer({0x4bde98, 0xc00011e050}, {0x4bddb8, 0xc00012e018}, {0x0, 0x0, 0x0}) /usr/lib/go/src/io/io.go:427 +0x1b2 io.Copy(...) /usr/lib/go/src/io/io.go:386 os.genericReadFrom(0x101c00002c500?, {0x4bddb8, 0xc00012e018}) /usr/lib/go/src/os/file.go:161 +0x67 os.(*File).ReadFrom(0xc00012e008, {0x4bddb8, 0xc00012e018}) /usr/lib/go/src/os/file.go:155 +0x1b0 io.copyBuffer({0x4bde38, 0xc00012e008}, {0x4bddb8, 0xc00012e018}, {0x0, 0x0, 0x0}) /usr/lib/go/src/io/io.go:413 +0x14b io.Copy(...) /usr/lib/go/src/io/io.go:386 main.pipetest() /home/stranger/source-code/golang/ipctest/pipes/main.go:39 +0x1ae main.main() /home/stranger/source-code/golang/ipctest/pipes/main.go:10 +0x17 goroutine 18 [chan send]: main.pipetest.func1() /home/stranger/source-code/golang/ipctest/pipes/main.go:29 +0x85 created by main.pipetest /home/stranger/source-code/golang/ipctest/pipes/main.go:26 +0x17a exit status 2
io.copy
不断尝试复制,直到读取器到达 eof(在本例中,当管道关闭时)。由于您在 io.copy
结束后调用 writer.close()
after ,因此 io.copy
不断尝试复制,直到读取器到达 eof(在本例中,当管道关闭时)。由于您在
writer.close()
after ,因此 将永远不会看到 eof,并永远挂起。close
able 对象只应关闭一次,并且在 close
d 后被假定为不可用。如果您需要重新使用它们,您应该创建一个新实例。
🎜这是代码的工作修订版:🎜func main() { c := make(chan string) go func() { for i := 0; i < 5; i++ { text := fmt.Sprintf("hello %vth time", i+1) c <- text } close(c) }() for msg := range c { msg = fmt.Sprintf("\nreceived from channel -> %v\n", msg) // Create a new pipe for this message. reader, writer := io.Pipe() go func() { fmt.Fprint(writer, msg) // Close the pipe after writing the message. writer.Close() }() io.Copy(os.Stdout, reader) } }
以上是尝试写入/读取时 io.Pipe 和死锁的详细内容。更多信息请关注PHP中文网其他相关文章!