这是一个使用 bufio.Scanner 和 fmt.Scanln 的简单程序,它按预期工作:
scanner := bufio.NewScanner(os.Stdin)
var s string
fmt.Println("Enter a string:")
scanner.Scan()
s = scanner.Text()
fmt.Printf("You entered: %q\n\n", s)
var i int
fmt.Println("Enter an int:")
fmt.Scanln(&i)
fmt.Printf("You entered: %d\n", i)
这是程序输出(括号内的文字[]是键盘输入)
Enter a string:
[mary had a little lamb]
You entered: "mary had a little lamb"
Enter an int:
[42]
You entered: 42
现在,我们不使用默认的标准输入,而是使用管道从字符串而不是键盘重定向输入。
readStdin, writeStdin, err := os.Pipe()
if err != nil {
fmt.Println("Pipe Error:", err)
return
}
os.Stdin = readStdin
writeStdin.WriteString("mary had a little lamb\n42\n")
scanner := bufio.NewScanner(os.Stdin)
var s string
fmt.Println("Enter a string:")
scanner.Scan()
s = scanner.Text()
fmt.Printf("You entered: %q\n\n", s)
var i int
fmt.Println("Enter an int:")
fmt.Scanln(&i)
fmt.Printf("You entered: %d\n", i)
readStdin.Close()
这是程序输出:Enter a string:
You entered: "mary had a little lamb"
Enter an int:
在“Enter an int:”提示后,程序无限期等待,必须手动终止。 :(奇怪的是,如果我颠倒事件的顺序(fmt.Scanln 在 bufio.Scanner.Scan 之前),那么它会完美运行。如果我专门使用 fmt.Scanln 或专门使用 bufio.Scanner.Scan,它也可以正常工作。
所有这些都让我想到:
a) Go 处理键盘输入的方式有一些独特的不同
b) 使用 bufio.Scanner.Scan 扫描时,我应该使用其他类型的分隔符
c) 永远不要同时使用这两种扫描机制(请不要让这成为答案!)
最佳答案
bufio.Scanner
使用缓冲区读取输入 block ,然后返回该缓冲区的部分。当您使用管道写入完整的输入时,bufio.Scanner
只需读取整个输入,并返回由换行符分隔的两个标记。 fmt.Scanln
将始终从标准输入读取。到时候fmt.Scanln
运行,bufio.Scanner
已经读取了完整的输入,所以 fmt.Scanln
只是等待。如果您在开头设置 sleep 并在程序开始读取之前键入所有输入,第一个程序也会发生同样的事情。所以这与 Go 如何处理输入或扫描分隔符无关。
如果你使用缓冲 i/o,你必须期望缓冲区有比你需要的更多的东西。所以,不要将两者混用,或者使用 fmt.Scanln
在您完全使用扫描仪后。
关于go - 如何按顺序将字符串输入输入 bufio.Scanner 和 fmt.Scanln?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63211081/