1

我正在尝试编写一个函数,该函数可以一次从键盘读取输入或从管道文件中读取一行。我已经有一个类似于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()read all of中制作的a.txt。我可以通过创建bufio.Scanner一个全局变量并prompt()使用它而不是每次都创建一个新变量来轻松解决这个问题bufio.Scanner,但我想知道是否有更好的方法来做到这一点而不必求助于全局变量。

4

2 回答 2

1

您的分析是正确的,问题在于bufio.Scanner缓冲的文本不止一行,因此当您将其丢弃时,您会丢失该输入。如果要使用缓冲输入,则应确保所有内容都使用相同的缓冲区以避免此类问题。

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

于 2013-10-24T08:03:37.900 回答
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()
}
于 2013-10-24T08:06:06.720 回答