使用io.Pipes()发送和接收消息

Pha*_*aoh 0 go

我在程序中使用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:无效的参数

Jim*_*imB 5

您正在使用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)