我在程序中使用os.Pipes(),但是由于某种原因,每次我尝试从中写入或读取数据时,它都会给出错误的文件描述符错误。
我做错了什么吗?
下面是代码
package main
import (
"fmt"
"os"
)
func main() {
writer, reader, err := os.Pipe()
if err != nil {
fmt.Println(err)
}
_,err= writer.Write([]byte("hello"))
if err != nil {
fmt.Println(err)
}
var data []byte
_, err = reader.Read(data)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(data))
}
Run Code Online (Sandbox Code Playgroud)
输出:写入| 0:无效的参数读取| 1:无效的参数
您正在使用os.Pipe,从os返回一对FIFO连接文件。这与io.PipeGo中实现的有所不同。
该invalid argument错误是因为你正在读取和写入到错误的文件。的签名os.Pipe是
func Pipe() (r *File, w *File, err error)
Run Code Online (Sandbox Code Playgroud)
这表明返回值的顺序为“读取器,写入器,错误”。
和io.Pipe:
func Pipe() (*PipeReader, *PipeWriter)
Run Code Online (Sandbox Code Playgroud)
还按“读者,作家”的顺序返回
当您检查os.Pipe功能中的错误时,您仅在打印该值。如果有错误,则文件无效。您需要返回或退出该错误。
管道也在阻塞(尽管os.Pipe具有小的硬编码缓冲区),因此您需要异步读取和写入。如果将其换成一个io.Pipe,它将立即死锁。在goroutine中调度Read方法,然后等待其完成。
最后,您正在读入一个nil切片,该切片将不会读取任何内容。您需要分配要读取的空间,并且需要记录读取的字节数以了解使用了多少缓冲区。
您的示例的更正确版本如下所示:
reader, writer, err := os.Pipe()
if err != nil {
log.Fatal(err)
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
data := make([]byte, 1024)
n, err = reader.Read(data)
if n > 0 {
fmt.Println(string(data[:n]))
}
if err != nil && err != io.EOF {
fmt.Println(err)
}
}()
_, err = writer.Write([]byte("hello"))
if err != nil {
fmt.Println(err)
}
wg.Wait()
Run Code Online (Sandbox Code Playgroud)