英文:
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()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论