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

huangapple go评论91阅读模式
英文:

using io.Pipes() for sending and receiving message

问题

我正在使用os.Pipe()在我的程序中,但是每次尝试从中写入或读取数据时,它都会出现一个坏的文件描述符错误。

我做错了什么吗?

以下是代码:

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))
}

输出:
write |0: Invalid argument
read |1: Invalid argument

英文:

I am using os.Pipes() in my program, but for some reason it gives a bad file descriptor error each time i try to write or read data from it.

Is there some thing I am doing wrong?

Below is the code

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))
}

output :
write |0: Invalid argument
read |1: Invalid argument

答案1

得分: 6

您正在使用os.Pipe来创建一对连接的FIFO文件。这与Go语言中实现的io.Pipe不同。

"invalid argument"错误是因为您正在读取和写入错误的文件。os.Pipe的签名是:

func Pipe() (r *File, w *File, err error)

这表明返回值的顺序是"读取器,写入器,错误"。

io.Pipe的签名是:

func Pipe() (*PipeReader, *PipeWriter)

同样按照"读取器,写入器"的顺序返回。

当您检查os.Pipe函数的错误时,您只是打印了该值。如果有错误,文件是无效的。您需要在该错误上返回或退出。

管道也是阻塞的(尽管os.Pipe有一个小的、硬编码的缓冲区),所以您需要异步读取和写入。如果您将其替换为io.Pipe,它将立即发生死锁。将Read方法分派到一个goroutine中,并等待其完成。

最后,您正在将数据读入一个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()
英文:

You are using an os.Pipe, which returns a pair of FIFO connected files from the os. This is different than an io.Pipe which is implemented in Go.

The invalid argument errors are because you are reading and writing to the wrong files. The signature of os.Pipe is

func Pipe() (r *File, w *File, err error)

which shows that the returns values are in the order "reader, writer, error".

and io.Pipe:

func Pipe() (*PipeReader, *PipeWriter)

Also returning in the order "reader, writer"

When you check the error from the os.Pipe function, you are only printing the value. If there was an error, the files are invalid. You need to return or exit on that error.

Pipes are also blocking (though an os.Pipe has a small, hard coded buffer), so you need to read and write asynchronously. If you swapped this for an io.Pipe it would deadlock immediately. Dispatch the Read method inside a goroutine and wait for it to complete.

Finally, you are reading into a nil slice, which will read nothing. You need to allocate space to read into, and you need to record the number of bytes read to know how much of the buffer is used.

A more correct version of your example would look like:

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()

huangapple
  • 本文由 发表于 2016年12月21日 21:24:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/41263834.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定