1、io.Copy(dst Writer, src Reader)(written int64, err error)
haypin@MBP /usr/local/go/src/os go doc io.Copy
package io // import "io"
func Copy(dst Writer, src Reader) (written int64, err error)
Copy copies from src to dst until either EOF is reached on src or an error
occurs. It returns the number of bytes copied and the first error
encountered while copying, if any.
io.Copy拷贝src的副本到dst直到EOF到达或发生一个错误。它返回拷贝的字节数或在拷贝时遇到的第一个错误,这意味着io.Copy函数内部是死循环拷贝src的副本到dst的,如果要死循环侦听标准输入os.Stdin并拷贝到标准输出os.Stdout,可以使用io.Copy(os.Stdou,os.Stdin):
package main
import (
"io"
"os"
)
func main() {
//1、io.Copy(dst Writer,src Reader)(written int64,err error)拷贝src的副本
//到dst直到EOF到达或发生一个错误。返回拷贝的字节数或在拷贝时遇到的第一个错误
io.Copy(os.Stdout, os.Stdin)
}
HaypinsMBP:Temp haypin$ go run stdin.go
heihei
heihei
haha
haha
^Csignal: interrupt
HaypinsMBP:Temp haypin$
所以没必要自己另外嵌套一层死循环:
for {
_, err := io.Copy(os.Stdout, os.Stdin)
if err == io.EOF {
fmt.Printf("输入结束\n")
break
} else if err != nil {
fmt.Printf("输入异常\n")
break
} else if err == nil {
fmt.Printf("继续输入:\n")
continue
}
}
fmt.Printf("程序结束\n")
haypin@MBP /usr/local/go/src grep -e package\ io -r .
./io/example_test.go:package io_test
./io/ioutil/example_test.go:package ioutil_test
./io/ioutil/tempfile.go:package ioutil
./io/ioutil/ioutil.go:package ioutil
./io/ioutil/ioutil_test.go:package ioutil_test
./io/ioutil/export_test.go:package ioutil
./io/ioutil/tempfile_test.go:package ioutil_test
./io/multi_test.go:package io_test
./io/io.go:package io
io.Copy()的详细说明:
$GOROOT/io/io.go:
// Copy copies from src to dst until either EOF is reached
// on src or an error occurs. It returns the number of bytes
// copied and the first error encountered while copying, if any.
//
// A successful Copy returns err == nil, not err == EOF.
// Because Copy is defined to read from src until EOF, it does
// not treat an EOF from Read as an error to be reported.
//
// If src implements the WriterTo interface,
// the copy is implemented by calling src.WriteTo(dst).
// Otherwise, if dst implements the ReaderFrom interface,
// the copy is implemented by calling dst.ReadFrom(src).
func Copy(dst Writer, src Reader) (written int64, err error) {
return copyBuffer(dst, src, nil)
}
一个成功的Copy返回err==nil(并继续io.Copy的死循环)而不是err==EOF(将结束io.Copy()),因为Copy被定义为读取src直到EOF,它不会把Read的EOF视作一个要报告的错误(而是结束io.Copy的死循环)。
如果src实现了WriterTo接口,则io.Copy通过调用src.WriteTo(dst)实现。否则,如果dst实现了ReaderFrom接口,io.Copy将通过调用dst.ReadFrom(src)实现。
2、input:=bufio.NewScanner(os.Stdin); input.Scan()
haypin@MBP /usr/local/go/src go doc bufio.NewScanner
package bufio // import "bufio"
func NewScanner(r io.Reader) *Scanner
NewScanner returns a new Scanner to read from r. The split function defaults
to ScanLines.
haypin@MBP /usr/local/go/src
bufio.NewScanner(r io.Reader)*Scanner 返回从r读取内容的一个扫描器。分隔函数默认是ScanLines。
// Scan advances the Scanner to the next token, which will then be
// available through the Bytes or Text method. It returns false when the
// scan stops, either by reaching the end of the input or an error.
// After Scan returns false, the Err method will return any error that
// occurred during scanning, except that if it was io.EOF, Err
// will return nil.
// Scan panics if the split function returns too many empty
// tokens without advancing the input. This is a common error mode for
// scanners.
func (s *Scanner) Scan() bool {
func (s *Scanner) Scan() bool{}方法推进扫描器直到下一个标记,然后可以通过func (s *Scanner) Bytes或func (s *Scanner) Text方法使用扫描到的内容。当扫描停止、或抵达输入的结束、或者遇到一个错误时返回false。在Scan返回fasle后,Err方法将返回扫描期间发生的任何错误,而io.EOF(分隔标记)错误将返回nil。
input := bufio.NewScanner(os.Stdin)
if err := input.Scan(); err == true { //将只从扫描器对象扫描一次输入(以换行符分隔)
fmt.Fprintf(os.Stdout, input.Text()+"\n")
} else { //比如
fmt.Printf("扫描输入异常panic或终止io.EOF\n")
}
HaypinsMBP:Temp haypin$ go run stdin.go
ha
ha
HaypinsMBP:Temp haypin$
而要死循环扫描输入:
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
fmt.Fprintf(os.Stdout, input.Text()+"\n")
}
HaypinsMBP:Temp haypin$ go run stdin.go
heihei
heihei
papa
papa
haha
haha
^Csignal: interrupt
HaypinsMBP:Temp haypin$
for input.Scan(){}等价于for ok:=input.Scan();ok;ok=input.Scan(){}
input := bufio.NewScanner(os.Stdin)
for ok := input.Scan(); ok; ok = input.Scan() {
// for input.Scan() {
// fmt.Fprintf(os.Stdout, input.Text()+"\n")
fmt.Printf("%t %s\n", ok, input.Text())
}
注意到for input.Scan(){}其实就是for ok:=input.Scan();ok;ok=input.Scan(){}的等价形式。