go - 如何按顺序将字符串输入输入 bufio.Scanner 和 fmt.Scanln?

标签 go pipe stdin gofmt

这是一个使用 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/

相关文章:

python - 在向标准输出显示消息时不要打扰用户输入

C 初学者 : Does scanf "receive" the EOF marker from standard input?

go - 如何将带有整数和零的数组转换为字符串?

go - GO 中的包/函数中毒

angular - TypeError : Cannot read property 'sort' of undefined at SortPipe. 转换,为什么?

c++ - 串联加入 3 个 C++ 程序

c - 我如何在标准输入中寻找

Go接口(interface)属性未定义

mongodb - mgo 和 mongodb 的 i/o 超时

child 使用管道进行计算