2013-10-24 53 views
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! 

据我了解,这是因为在greet()中制作的bufio.Scanner读取了全部a.txt。通过将bufio.Scanner设置为全局变量,我可以很容易地解决这个问题,并且每次都使用prompt()而不是创建一个新的bufio.Scanner,但我想知道是否有更好的方法来做到这一点,而不必诉诸于全局变量。

回答

1

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

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

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() 
}