GoLang – 为什么将日志记录到标准输入(stdin)是有效的?

huangapple go评论68阅读模式
英文:

GoLang - why is logging to stdin valid?

问题

log.New(os.Stdin, "in", 1).Println("TT")

以下代码的输出流看起来应该使用stdout或stderr,但我正在使用stdin输入流。
它应该会引发一些错误,但正常情况下会输出到控制台。

为什么这个代码能正常工作呢?
我不知道为什么。

嗯,难道输入流不是用来从键盘输入吗?但是由于我将输入流用于输出,我认为这不应该起作用。stdout:控制台,stderr:控制台,stdin:键盘

英文:
log.New(os.Stdin, "in", 1).Println("TT")

The following code out stream looks like it should use stdout or stderr, but I'm using the stdin input stream.
It should go into some panic, but output to the console normally.

Why is this working fine?
I don't know why.

um Isn't stream input used to type on the keyboard? But since I input stream input to output, I don't think this should work. stdout:console,
stderr:console,
stdin:keyboard

答案1

得分: 3

TL;DR - 从源代码中:

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 是指向标准输入、标准输出和标准错误文件描述符的打开文件。

实际上,这意味着 Go 将 Stdin、Stdout 和 Stderr 视为普通的文件。为什么不呢?因为它们确实就是普通的文件。如果你在你选择的 shell 中运行 echo sometext > /dev/stdin,你会发现这是有效的,并且文本 "sometext" 将被打印到终端上。

深入探讨

让我们来看一下 log.New 函数的声明:

func New(out io.Writer, prefix string, flag int) *Logger

New 创建一个新的 Logger。out 变量设置了日志数据将被写入的目标。prefix 出现在每个生成的日志行的开头,或者在提供了 Lmsgprefix 标志后的日志头之后。flag 参数定义了日志的属性。

你可以看到第一个参数是 io.Writer 接口,它被声明为:

type Writer interface {
	Write(p []byte) (n int, err error)
}

这实际上意味着 log.New 接受了每个具有 Write(p []byte) (n int, err error) 方法的结构体。而因为 os.Stdin 的类型是 os.File,它符合 io.Writer 接口的规范和 log.New 的签名。

英文:

TL;DR - From the source code:

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.

what this actually means is that Go treats Stdin, Stdout and Stderr the same, just as regular Files. and why shouldn't it? that's really just what they are. If you run echo sometext > /dev/stdin in your shell of choice, you'll see that this is valid and the text "sometext" will be printed to the terminal

Digging Deeper

Let's examine the log.New function declaration:

func New(out io.Writer, prefix string, flag int) *Logger

> New creates a new Logger. The out variable sets the destination to
> which log data will be written. The prefix appears at the beginning of
> each generated log line, or after the log header if the Lmsgprefix
> flag is provided. The flag argument defines the logging properties.

You can see that the first argument is the io.Writer interface - which is declared as :

type Writer interface {
	Write(p []byte) (n int, err error)
}

This effectively means that log.New accepts every struct that has a Write(p []byte) (n int, err error) method. And because os.Stdin is of type os.File, it matches the io.Writer interface specification and the signature of log.New.

huangapple
  • 本文由 发表于 2022年3月10日 19:23:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/71423309.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定