<p>This code snippet is from a book I am working through, in this example it's just to teach some syntax with finding duplicate strings as the example. </p>
<p>Pay attention to the countLines() function at the bottom, which takes in parameter f of type *os.File. When files are passed into the program, it opens those files up to pass in the *os.File pointers just as the function expects, but in one case, where no files are passed in, os.Stdin is passed in to the same function...and works perfectly. Why does this work?</p>
<pre><code>import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]int)
files := os.Args[1:]
if len(files) == 0 {
countLines(os.Stdin, counts)
} else {
for _, arg := range files {
f, err := os.Open(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
continue
}
countLines(f, counts)
f.Close()
}
}
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}
func countLines(f *os.File, counts map[string]int) {
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
</code></pre>
<p>} </p>
<hr/>**评论:**<br/><br/>not_legally_rape: <pre><p>os.Stdin, os.Stdout, and os.Stderr are all *Files because they predate the io.Reader and io.Writer interfaces. This will probably be changed eventually.</p></pre>weberc2: <pre><p>Genuinely curious--where did you get this information (that they will be changed eventually)? On many OSes, stdin, stdout, and stderr <em>are</em> files, so it seems odd that they <em>wouldn't</em> be *os.File objects. What would their type be if not *os.File?</p></pre>TheMerovius: <pre><blockquote>
<p>Genuinely curious--where did you get this information (that they will be changed eventually) </p>
</blockquote>
<p>People from the go team have mentioned on go-nuts and similar, that this should have happened for go1 and might happen in go2, at some point.</p>
<blockquote>
<p>On many OSes, stdin, stdout, and stderr are files</p>
</blockquote>
<p>But that doesn't mean that those variables need to have that type. The file handles obviously must be files and on start-up there would be <code>*os.File</code>s in those variables, but that doesn't need to <em>stay</em> that way.</p>
<blockquote>
<p>What would their type be if not *os.File?</p>
</blockquote>
<p><code>io.Reader</code> resp. <code>io.Writer</code>. The point of that is, that you can then replace them with your own Reader/Writer for tests and other things. </p></pre>weberc2: <pre><blockquote>
<p>But that doesn't mean that those variables need to have that type. The file handles obviously must be files and on start-up there would be *os.Files in those variables, but that doesn't need to stay that way.</p>
</blockquote>
<p>I wasn't arguing that it <em>needed</em> to be that way; but I assumed the proposed change wasn't only for change's sake?</p>
<blockquote>
<p>io.Reader resp. io.Writer.</p>
</blockquote>
<p>So what would be the type of the thing underlying the interface? Or perhaps you mean to suggest that that would be private?</p></pre>barsonme: <pre><p>This will answer all your questions: <a href="https://github.com/golang/go/issues/14106" rel="nofollow">https://github.com/golang/go/issues/14106</a></p></pre>weberc2: <pre><p>Yeah, someone already linked. Thanks though! :)</p></pre>TheMerovius: <pre><blockquote>
<p>So what would be the type of the thing underlying the interface?</p>
</blockquote>
<p><code>*os.File</code> (btw: There is an argument to be made for <code>os.File</code> to be <em>itself</em> an interface, to wrap different kinds of files. But that is not what this is about). The only change is, that you could then use <em>other</em> Readers/Writers to put in there, so that stuff that uses it (e.g. <code>fmt</code> or <code>log</code> packages) would write to your implementation.</p></pre>not_legally_rape: <pre><p>Stole it all from: <a href="https://github.com/golang/go/issues/13473" rel="nofollow">https://github.com/golang/go/issues/13473</a></p></pre>weberc2: <pre><p>Gotcha, thanks for the info! :)</p></pre>mcouturier: <pre><p><a href="https://golang.org/pkg/os/" rel="nofollow">https://golang.org/pkg/os/</a></p>
<blockquote>
<p>Stdin, Stdout, and Stderr are open Files pointing to the standard input, standard output, and standard error file descriptors.</p>
</blockquote></pre>weberc2: <pre><p>I'm aware of what their type is today; I was asking what it would be if they changed the type. At any rate, <a href="/u/Merovius" rel="nofollow">/u/Merovius</a> already answered.</p></pre>mcouturier: <pre><p>Oh right sorry misread your comment..</p></pre>Stryfex19: <pre><p>Thank you for this and your github link below!!</p></pre>adrianojn: <pre><pre><code>$ godoc os Stdin
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
</code></pre>
<p>Stdin, Stdout, and Stderr are open Files pointing to the standard input, standard output, and standard error file descriptors.</p></pre>Stryfex19: <pre><p>Thank you!!</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传