我想从围棋程序的原版stdin
读一读.例如,如果我使用echo test stdin | go run test.go
,我会希望能够访问"test stdin".我试着从os.Stdin
开始读取,但是如果里面什么都没有,那么它将等待输入.我也try 先判断大小,但即使传入输入,os.Stdin.Stat().Size()
也是0.
我能做什么?
我想从围棋程序的原版stdin
读一读.例如,如果我使用echo test stdin | go run test.go
,我会希望能够访问"test stdin".我试着从os.Stdin
开始读取,但是如果里面什么都没有,那么它将等待输入.我也try 先判断大小,但即使传入输入,os.Stdin.Stat().Size()
也是0.
我能做什么?
I think your question per se has no sensible answer because there's just no such thing as "initial stdin". Unix-like OSs, and Windows implement the concept of "standard streams", which works like this (simplified): when a process is created, it automagically has three file descriptors (handles in Windows) open — stdin, stdout and stderr. No doubts, you're familiar with this concept, but I'd like to stress the meaning of the word "stream" there — in your example, when you call
$ echo 'test stdin' | ./stdin
the shell creates a pipe, spawns two processes (one for echo
and one for your binary) and makes use of the pipe it created: the pipe's write FD is attached to the echo
's stdout and the pipe's read FD is attached to your binary's stdin. Then whatever the echo
process pleases to write to its stdout is piped (sic!) to the stdin of your process.
(In reality most today's shells implement echo
as a built-in primitive but this does not in any way change the semantics; your could as well have tried /bin/echo
instead, which is a real program. Also note that I just used ./stdin
to refer to your program — this is for clarity, as go run stdin.go
would do exactly this, in the end.)
请注意以下几点:
echo
)不会被忽略以向其标准输出写入任何内容(例如,echo -n
不会向其标准输出写入任何内容并成功退出).read
,但调用失败)之后.让我们来总结一下:你观察到的行为是正确和正常的.如果您希望从stdin获得任何数据,则不能期望这些数据随时可用.如果您也不想在标准输入上使用挡路,那么创建一个goroutine,它将在一个无限循环中对标准输入执行阻塞读取(但判断EOF条件),并通过通道向上传递收集到的数据(如果需要,可能在进行了某些处理之后).
1 This is why certain tools which usually occur between two pipes in a pipeline, such as grep
, might have special options to make them flush their stdout after writing each line — read about the --line-buffered
option in the grep
manual page for one example. People who are not aware of this "full buffering by default" semantics are puzzled why tail -f /path/to/some/file.log | grep whatever | sed ...
seems to stall and not display anything when it's obvious the monitored file gets updated.
附注:如果您要"按原样"运行您的二进制文件,如下面的
$ ./stdin
这并不意味着生成的进程将没有stdin(或"initial stdin"或whavier),相反,它的stdin将连接到shell从中接收键盘导入的同一个流(因此可以直接在进程的stdin中键入内容).
将进程的标准输入连接到任何地方的唯一可靠方法是使用
$ ./stdin </dev/null
在类Unix操作系统和
C:\> stdin <NUL
在windows 上.这"null device"使过程在其标准输入的第一个read
上看到EOF.