在具有
io.ReadWriteCloser
实例的 golang 中,如何获取其表示(代理类型)作为 *os.File
实例(例如为 exec.Cmd.ExtraFiles
提供)
首先想到的是使用
os.Pipe
方法。但这样的存根仍然是单向的(只读或只写)。
那么如何将
io.ReadWriteCloser
完全表示为*os.File
例如
func something(stream io.ReadWriteCloser) {
cmd := exec.Command("comm")
var wrapped *os.File = wrappAsFile(stream) // How this could be achieved?
cmd.ExtraFiles := []*File{wrapped}
}
我可以看到的简化解决方案如下所示。尽管如此(正如我之前提到的)它只涵盖了 Reader 流程。
func something(stream io.ReadWriteCloser) {
cmd := exec.Command("comm")
r, w, _ := os.Pipe()
go func() {
io.Copy(w, stream)
w.Close()
}()
cmd.ExtraFiles := []*File{r}
}
谢谢
socketpair
创建全双工管道。您可以通过 golang.org/x/sys/unix
包作为 syscall.Socketpair
访问此内容
func socketpair() (*os.File, *os.File, error) {
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
if err != nil {
return nil, nil, err
}
if err := syscall.SetNonblock(int(fds[0]), true); err != nil {
return nil, nil, err
}
if err := syscall.SetNonblock(int(fds[1]), true); err != nil {
return nil, nil, err
}
f0 := os.NewFile(uintptr(fds[0]), "socket-0")
f1 := os.NewFile(uintptr(fds[1]), "socket-1")
return f0, f1, nil
}
然后您可以通过几个
io.ReadWriteCloser
调用连接到 io.Copy
:
// We'll use f0 as the local side of the pipe, and pass along f1 to the child process
f0, f1, err := socketpair()
if err != nil {
log.Fatal(err)
}
go func() {
io.Copy(f0, rw)
f0.Close()
}()
go func() {
io.Copy(rw, f0)
}()