这里有一个使用bufio的简单程序。扫描仪和fmt。正常工作的扫描:
scanner := bufio.NewScanner(os.Stdin)
var s string
fmt.Println("Enter a string:")
scanner.Scan()
s = scanner.Text()
fmt.Printf("You entered: %qnn", s)
var i int
fmt.Println("Enter an int:")
fmt.Scanln(&i)
fmt.Printf("You entered: %dn", i)
这是程序输出(括号内的文本[]是键盘输入(
Enter a string:
[mary had a little lamb]
You entered: "mary had a little lamb"
Enter an int:
[42]
You entered: 42
现在,让我们使用管道来重定向来自字符串而不是键盘的输入,而不是使用默认的stdin。
readStdin, writeStdin, err := os.Pipe()
if err != nil {
fmt.Println("Pipe Error:", err)
return
}
os.Stdin = readStdin
writeStdin.WriteString("mary had a little lambn42n")
scanner := bufio.NewScanner(os.Stdin)
var s string
fmt.Println("Enter a string:")
scanner.Scan()
s = scanner.Text()
fmt.Printf("You entered: %qnn", s)
var i int
fmt.Println("Enter an int:")
fmt.Scanln(&i)
fmt.Printf("You entered: %dn", i)
readStdin.Close()
这是程序输出:
Enter a string:
You entered: "mary had a little lamb"
Enter an int:
在";输入一个int:"提示时,程序将无限期等待,并且必须手动终止。:(
奇怪的是,如果我颠倒事件的顺序(在bufio.Scanner.Scan之前是fmt.Scanln(,那么它就可以完美地工作。如果我只使用fmt,它也可以正常工作。扫描或专用bufio。扫描仪。扫描。
所有这些都让我思考:
a( Go处理键盘输入的方式有一些独特的不同
b(在使用bufio扫描时,我应该使用其他类型的分隔符。扫描仪。扫描
c(永远不要同时使用这两种扫描机制(请不要让这成为答案!(
bufio.Scanner
使用缓冲区读取输入的块,然后返回该缓冲区的部分。当您使用管道编写完整的输入时,bufio.Scanner
只读取整个输入,并返回由换行符分隔的两个标记。fmt.Scanln
将始终从stdin读取。到fmt.Scanln
运行时,bufio.Scanner
将已经读取完整的输入,因此fmt.Scanln
只是等待。如果你在第一个程序开始时进入睡眠状态,并在程序开始读取之前键入所有输入,那么第一个程序也会发生同样的情况。因此,这与Go如何处理输入或扫描分隔符无关。
如果你使用缓冲的i/o,你必须期望缓冲区有比你需要的更多的东西。因此,不要将两者混合使用,或者在完全用完扫描仪后使用fmt.Scanln
。