英文:
Why operate normally when bufio.NewWriter get os.Stdin in local
问题
package main
import (
"bufio"
"os"
)
func main() {
bw := bufio.NewWriter(os.Stdin)
bw2 := bufio.NewWriter(os.Stdout)
bw.WriteString("你好,世界 1\n")
bw2.WriteString("你好,世界 2\n")
bw.Flush()
bw2.Flush()
}
这段代码在本地环境中显示了两个字符串。但为什么在不同的环境中表现不同呢?
我的本地环境:
操作系统:macOS 12.6
Go 版本:go1.19.2 darwin/amd64
IDE:vscode
- 在我的本地机器上运行:
$ go run myworkspace/main/main.go
你好,世界 1
你好,世界 2
- 在 playground 上运行:
# 在 'Output' 部分
---
你好,世界 2
程序已退出。
英文:
package main
import (
"bufio"
"os"
)
func main() {
bw := bufio.NewWriter(os.Stdin)
bw2 := bufio.NewWriter(os.Stdout)
bw.WriteString("Hello, world 1\n")
bw2.WriteString("Hello, world 2\n")
bw.Flush()
bw2.Flush()
}
This code show both string in a local environment.
But why does it work differently in different environments?
My local environment
OS : macOS 12.6
go : go1.19.2 darwin/amd64
ide : vscode
- on my local machine :
$ go run myworkspace/main/main.go
Hello, world 1
Hello, world 2
- on the playground :
# in the 'Output' section
---
Hello, world 2
Program exited.
答案1
得分: 2
Go Playground
https://go.dev/play/p/PtoDwCZGggd
向下滚动到“关于Playground”
关于Playground
Go Playground在一个沙盒中运行程序。
Playground有一些限制:
Playground程序与外界的唯一通信方式是通过标准输出和标准错误输出。
Go Playground会忽略对标准输入的写入。
在本地,os.Stdin
是一个文件。
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
Stdin、Stdout和Stderr是打开的文件,指向标准输入、标准输出和标准错误的文件描述符。
英文:
The Go Playground
https://go.dev/play/p/PtoDwCZGggd
Scroll all the way down to "About the Playground"
> About the Playground
>
> The Go Playground runs the program inside a sandbox.
>
> There are limitations to the programs that can be run in the playground:
>
> The only communication a playground program has to the outside world is by writing to standard output and standard error.
The Go Playground discards writes to standard input.
Locally, os.Stdin
is a file.
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
> Stdin, Stdout, and Stderr are open Files pointing to the standard input, standard output, and standard error file descriptors.
答案2
得分: 2
底线是:当程序启动时,你的程序无法控制将使用什么作为标准输入和标准输出。
在你的本地机器上尝试运行:echo "" | go run main.go
或 go run main.go < anyfile
。
(另外:你应该在你的Go代码中检查错误)
在从终端运行命令时,标准设置是,shell使用相同的文件描述符,该文件描述符指向一个读/写终端,用于标准输入和标准输出/标准错误。在这种设置下,写入标准输入是“可行的”。
但是你不能依赖它(实际上你不应该这样做),事实证明playground不是以这种方式启动它的进程:
package main
import (
"fmt"
"os"
)
func main() {
_, err := os.Stdin.Write([]byte("Hello\n"))
if err != nil {
fmt.Fprintln(os.Stderr, "*** error:", err)
}
}
// 输出:
// *** error: write /dev/stdin: bad file descriptor
//
// 程序已退出。
https://go.dev/play/p/NmxgOsK2ovp
另请参阅:
https://stackoverflow.com/questions/37822580/why-is-it-possible-to-write-to-stdin
(通过搜索“writing to stdin”找到的)
英文:
The bottom line is : your program does not control what thingy will be used as Stdin and Stdout when it is started.
On your local machine, try running : echo "" | go run main.go
or go run main.go < anyfile
.
(also : you should check for errors in your go code)
It is a standard setup, when running a command from a terminal, that the shell uses the same file descriptor, which points to a read/write terminal, for stdin and stdout/stderr. With that setup, writing to stdin "works".
But you can't rely on it (you shouldn't, actually), and it turns out that the playground doesn't start its processes that way :
package main
import (
"fmt"
"os"
)
func main() {
_, err := os.Stdin.Write([]byte("Hello\n"))
if err != nil {
fmt.Fprintln(os.Stderr, "*** error:", err)
}
}
// Output:
// *** error: write /dev/stdin: bad file descriptor
//
// Program exited.
https://go.dev/play/p/NmxgOsK2ovp
see also :
https://stackoverflow.com/questions/37822580/why-is-it-possible-to-write-to-stdin
(found by googling "writing to stdin")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论