go-键盘或管道文件输入

go-键盘或管道文件输入,go,stdin,Go,Stdin,我正在尝试编写一个函数,可以从键盘读取输入,或者一次读取一行管道输入文件。在本测试代码中,我已经有了一个接受类似于prompt()的键盘输入的函数: package main import ( "fmt" "bufio" "os" ) func print(format string, a ...interface{}) { fmt.Printf(format+"\n", a...) } func prompt(format string) string {

我正在尝试编写一个函数,可以从键盘读取输入,或者一次读取一行管道输入文件。在本测试代码中,我已经有了一个接受类似于
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
,程序将输出:

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!

据我所知,这是因为在
greet()
中制作的
bufio.Scanner
读取了所有
a.txt
。我可以通过使
bufio.Scanner
成为一个全局变量来轻松解决这个问题,并让
prompt()
每次都使用它,而不是创建一个新的
bufio.Scanner
,但我想知道是否有更好的方法来做到这一点,而不必求助于全局变量。

您的分析是正确的,问题是,
bufio.Scanner
缓冲的文本超过一行,所以当你扔掉它时,你会丢失输入。如果要使用缓冲输入,应确保所有内容都使用相同的缓冲区,以避免此类问题


使用全局变量是一种解决方案。另一种方法是创建一个类型来保存
bufio.Scanner
,并将一些函数转换为方法。

我想说,由于
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()
}