Golang的终端循环输入io.Copy(*,os.Stdin)

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(){}的等价形式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值