找出正在发生的事情的最佳方法是查看标准库中的代码。最简单的方法就是用谷歌搜索:
https://www.google.com/search?q=os.Stdin
前几个链接中有一个网址
pkg.go.dev/os
在那里你可以找到标准输入的定义:
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
那么 NewFile 生成什么函数呢?
https://pkg.go.dev/os#NewFile
NewFile 返回具有给定文件描述符和名称的新文件。如果 fd 不是有效的文件描述符,则返回值将为 nil。在 Unix 系统上,如果文件描述符处于非阻塞模式,NewFile 将尝试返回一个可轮询文件(SetDeadline 方法适用的文件)。
将其传递给 NewFile 后,fd 可能会在 Fd 方法的 cmets 中描述的相同条件下变得无效,并且适用相同的约束。
这意味着 NewFile 将返回指向表示文件的结构的指针。
// File represents an open file descriptor.
type File struct {
*file // os specific
}
好的,这意味着 os.Stdin 代表一个文件。但是我们可以用那个 File 结构上的指针做什么呢?如果我们将其用作 fmt.Println 的参数,我们将获得该指针存储在内存中的地址。但是该结构具有 Read 方法。我们可以在 os/file.go 文件中找到为该 File 结构实现的所有方法。
https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/os/file.go;l=112;drc=a25c58462992704dbb6819769f530b6cc6a8ebe3
有一个 Read 方法可以将底层文件中的字节读取到作为方法参数提供的字节数组中。
package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
byteSlice := []byte{}
b1 := make([]byte, 1)
for {
_, err := os.Stdin.Read(b1)
if err == io.EOF {
break
}
if err != nil {
log.Printf("Unknown error: %+v ", err.Error())
os.Exit(1)
}
byteSlice = append(byteSlice, b1...)
}
fmt.Printf("we read: %s \n", string(byteSlice))
}
此代码效率极低,应仅用于演示目的。但我希望您了解如何从 os.Stdin 中读取以及 stdin 代表什么。