我正在尝试编写一个函数,该函数可以从键盘读取输入或一次读取一个管道文件。我已经有一个函数在这个测试代码中接受类似于prompt()
的键盘输入:
package main
import (
"fmt"
"bufio"
"os"
)
func print(format string, a ...interface{}) {
fmt.Printf(format+"\n", a...)
}
func prompt(format string) string {
fmt.Print(format)
in := bufio.NewScanner(os.Stdin)
in.Scan()
return in.Text()
}
func greet() {
name := prompt("enter name: ")
print(`Hello %s!`, name)
}
func humor() {
color := prompt("enter favorite color: ")
print(`I like %s too!`, color)
}
func main() {
greet()
humor()
}
此处,greet()
和humor()
都使用prompt()
来获取输入,如果我运行程序并输入响应,它将按预期工作。但是,如果我有一个文件a.txt
:
bobby bill
soft, blue-ish turquoise
然后运行:.\test< a.txt
,程序将输出:
enter name: Hello bobby bill!
enter favorite color: I like too!
而不是:
enter name: Hello bobby bill!
enter favorite color: I like soft, blue-ish turquoise too!
据我了解,这是因为bufio.Scanner
中的greet()
读取了所有a.txt
。我可以通过将bufio.Scanner
设为全局变量并prompt()
每次使用而不是创建新的bufio.Scanner
来轻松解决此问题,但我想知道是否有更好的方法这样做而不必求助于全局变量。
答案 0 :(得分:1)
您的分析是正确的,问题是bufio.Scanner
缓冲的不仅仅是一行文本,因此当您丢弃它时,您会丢失该输入。如果要使用缓冲输入,则应确保所有内容都使用相同的缓冲区以避免此类问题。
使用全局变量是一种解决方案。另一种方法是创建一个类型来保存bufio.Scanner
并将一些函数转换为方法。
答案 1 :(得分:1)
我想说,因为os.Stdin
是一个全局变量,所以拥有它的全局缓冲版本是完全合适的。
请注意,Go没有真正的全局变量 - 所有内容都始终位于包命名空间中,因此创建全局变量并不像C语言那么大。
例如
package main
import (
"bufio"
"fmt"
"os"
)
// Globals
var (
in = bufio.NewScanner(os.Stdin)
)
func prompt(format string) string {
fmt.Print(format)
in.Scan()
return in.Text()
}
func greet() {
name := prompt("enter name: ")
fmt.Printf("Hello %s!\n", name)
}
func humor() {
color := prompt("enter favorite color: ")
fmt.Printf("I like %s too!\n", color)
}
func main() {
greet()
humor()
}