gpt4 book ai didi

c++ - 是否可以在 Go 中使用类似 "freopen"的结构?

转载 作者:IT王子 更新时间:2023-10-29 02:29:50 26 4
gpt4 key购买 nike

在 C++ 中有一个 freopen 函数,它对于仅使用 stdin/out(cin/cout) 读/写文件非常有用。所以我决定在 Go 中寻找类似的解决方案,但只找到

import "os"
os.Stdin, err = os.OpenFile("input.txt",
os.RDONLY | os.O_CREATE, 0666)
os.Stdout, err = os.OpenFile("output.txt",
os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0666)

,它不再起作用了!我错了吗?那么,你知道其他方法吗?

最佳答案

虽然 Jeff Allen 提供了一个很好的答案,但那里提出的方法有一个小的低级“陷阱”:表示标准输出流新目的地的 os.File 值将引用文件不同于 stdout 和 stderr 的描述符操作系统所见。1

问题是,当进程在 POSIX 兼容系统上启动时,它的三个标准流分别打开文件描述符 0、1 和 2,分别用于标准输入、标准输出和标准错误。

因此,在某些代码依赖于标准流连接到标准文件描述符这一事实的模糊情况下,Jeff Allen 提供的代码将不太正确。

为了使其 100% 正确,我们可能依赖于另一个 POSIX 属性,该属性在打开新文件时重用最低的空闲文件描述符。因此,如果我们关闭代表一个标准流的文件并立即打开另一个标准流,那么新文件将使用刚刚关闭的标准流的文件描述符打开。为了保证在刚才介绍的步骤序列之间没有文件打开,我们必须在除了主协程之外的任何 goroutine 开始运行之前运行我们的代码——也就是说,在 main() 或任何 init ()

下面是演示这个想法的代码:

package main

import (
"os"
)

func init() {
err := os.Stdout.Close()
if err != nil {
panic(err)
}

fd, err := os.OpenFile("output.txt",
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
panic(err)
}

os.Stdout = fd
}

func main() {
myfd := os.NewFile(1, "")

_, err := myfd.Write([]byte("Direct output to FD 1\n"))
if err != nil {
panic(err)
}

_, err = os.Stdout.Write([]byte("Write to redirected os.Stdout\n"))
if err != nil {
panic(err)
}

os.Exit(1)
}

……这是它的工作原理:

$ go build
$ ./freopen
$ cat output.txt
Direct output to FD 1
Write to redirected os.Stdout

这可能看起来有点挑剔,但我认为值得解释一下正在发生的事情的“完整堆栈”。

哦,以这种方式重定向也将为外部观察者提供对进程的明智看法:比如说,在 Linux 上,通过类似的方式检查进程打开的文件描述符

$ vdir /proc/<pid>/fd

将提供合理的结果。


1 ...以及其他一切不了解 Go 的东西——例如,一些 C 代码中的链接调用类似 write(1, "OK\n", 3);

关于c++ - 是否可以在 Go 中使用类似 "freopen"的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35342020/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com