当前位置: 首页 > 面试题库 >

从Go的初始stdin中读取?

松茂实
2023-03-14
问题内容

我想阅读stdinGo程序的原始内容。例如,如果我这样做了echo test stdin | go run test.go,我希望可以访问“
test
stdin”。我尝试从中读取os.Stdin,但是如果其中没有任何内容,则它将等待输入。我也尝试过先检查大小,但是os.Stdin.Stat().Size()即使输入传入也为0。

我能做什么?


问题答案:

我认为您的问题本身没有明智的答案,因为没有“初始标准输入”之类的东西。类似于Unix的操作系统和Windows都实现了“标准流”的概念,它的工作原理如下(简化):创建进程时,它会自动打开三个文件描述符(Windows中的句柄)—
stdin,stdout和stderr。毫无疑问,您对这个概念很熟悉,但是我想强调一下“ stream”一词的含义-在您的示例中,当您调用

$ echo 'test stdin' | ./stdin

外壳程序创建一个管道,产生两个进程(一个为echo您的二进制文件,一个为您的二进制文件),并利用它创建的管道:该管道的write
FD附加到echo‘stdout,并且该管道的read
FD附加到二进制文件的stdin。然后,无论需要将echo哪个过程写入其标准输出,都将通过管道(原文如此!)传递到您的过程的标准输入。(实际上,当今大多数shell
echo都是作为内置基元实现的,但这并没有以任何方式改变语义;您也可以尝试/bin/echo使用它,它是一个真实的程序。还要注意,我只是用来./stdin指代您的程序-
最后是为了清楚起见,就像go run stdin.go这样做一样。)

请注意以下几个关键事项:

  • 写入过程(echo以您的情况为准)不会向其标准输出写入任何内容(例如,echo -n不会向其标准输出写入任何内容并成功退出)。
  • 它也能够任意延迟写入数据(或者是因为它想要进行此类延迟,或者是因为它已被操作系统抢占,或者由于某些系统调用而睡眠,等待一些繁忙的系统资源,等等)。
  • OS缓冲通过管道进行的传输。这意味着写入过程发送到管道的内容可能在读取端以任意块的形式出现。1个
  • 只有两种方法可以知道写入端没有更多数据可以通过管道发送:
    • 以某种方式在数据本身中对此进行编码(这意味着使用写入器和读取器之间达成一致的数据传输协议)。
    • 编写器可能会关闭管道的一侧,这会在读取器一侧导致“文件结束”状态(但仅在清空缓冲区并read尝试再次调用之后,失败)。

让我们总结一下:您观察到的行为是正确和正常的。如果希望从stdin获取任何数据,则不要期望它随时可用。如果您也不想在stdin上进行阻止,则创建一个goroutine,它将以无限循环的方式阻止对stdin的读取(但要检查EOF条件),并将收集到的数据通过通道向上传递(可能经过某些处理,如果需要)。

1这就是为什么某些工具在管道中两个管道之间通常会发生,比如grep,可能有特殊的选项,使它们写在每行后刷新它们的标准输出-阅读有关--line- buffered的选项grep手册页的一个例子。那些不了解这种“默认情况下完全缓冲”语义的人会感到困惑,为什么tail -f /path/to/some/file.log | grep whatever | sed ...当监视文件很明显被更新时,它似乎停滞并且什么也不显示。

附带说明:如果您要按原样运行二进制文件,例如

$ ./stdin

这并不意味着产生的进程将没有stdin(或“ initial
stdin”或whaveter),相反,它的stdin将连接到您的shell接收键盘输入的同一流(因此您可以直接在进程的stdin中键入内容)。

使进程的stdin无处连接的唯一确定方法是使用

$ ./stdin </dev/null

在类似Unix的操作系统

C:\> stdin <NUL

在Windows上。此“空设备”使进程read从其标准输入中首先看到EOF



 类似资料:
  • 问题内容: 是否可以从node.js中的stdin同步读取?因为我正在用JavaScript编写JavaScript编译器,所以很有趣。Brainfuck支持需要同步执行的读取操作。 我尝试了这个: 但这只会产生以下输出: 问题答案: 我不知道什么时候出现,但这是向前迈出的有益一步:http : //nodejs.org/api/readline.html 现在,我可以一次从stdin中读取行。快

  • 问题内容: 是否可以在正在运行的nodejs脚本中侦听传入的击键?如果我使用并监听其事件,则输入将被缓冲到下一个换行符,如下所示: 运行此,我得到: 我想要看的是: 我正在寻找一个等效于例如ruby的nodejs 这可能吗? 问题答案: 如果切换到原始模式,则可以通过这种方式实现:

  • 问题内容: 我正在使用以下命令行调用来处理带有node的文本文件: 文件的每一行都需要单独处理,但是一旦处理完,输入行可能会被忘记。 使用标准输入的数据侦听器,我得到了按字节大小分块的输入流,因此进行了设置。 但这似乎草率。必须在行数组的第一项和最后一项周围进行按摩。有没有更优雅的方式做到这一点? 问题答案: 您可以使用readline模块逐行从stdin进行读取:

  • 我想从STDIN读取输入。我在C中使用fork()方法。我有子进程和父进程。我的输入是多行的。父进程只等待子进程终止,子进程只读取第一行,子进程终止后,父进程继续读取。我想要打印行。例如;输入-> null 子进程打印“星期一”,父进程打印“星期二”和“星期三”。一旦到达文件结尾,程序就会终止。 ./program

  • 主要内容:变量初始化的标准格式,编译器推导类型的格式,短变量声明并初始化正如上一节《 Go语言变量声明》中提到的 Go语言在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值,例如: 整型和浮点型变量的默认值为 0 和 0.0。 字符串变量的默认值为空字符串。 布尔型变量默认为 bool。 切片、函数、指针变量的默认为 nil。 当然,依然可以在变量声明时赋予变量一个初始值。 回顾C语言 在C语言中,变量在声明时,并不会对变量对应内存区

  • 问题内容: 我一直在这样做,以便在Linux下同步读取整个stdin数据: 由于没有/ dev / stdin文件,因此这显然在Windows上不起作用。我该怎么做才能达到同样的目的? 问题答案: readline-sync模块可以很好地完成这项工作。 然后: https://www.npmjs.com/package/readline- sync