英文:
go - keyboard or piped-file input
问题
我正在尝试编写一个函数,可以从键盘读取输入,或者逐行从管道输入的文件中读取。我已经有一个函数,类似于测试代码中的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
来解决这个问题,但我想知道是否有更好的方法来解决这个问题,而不必使用全局变量。
英文:
I am trying to write a function that can read input from the keyboard or read from a piped-in file one line at a time. I already have a function that takes keyboard input similar to prompt()
in this test code:
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()
}
Here, greet()
and humor()
both use prompt()
to get the input, and if I run the program and type in the responses, it will work as expected. However, if I have a file a.txt
:
bobby bill
soft, blue-ish turquoise
and then run: .\test< a.txt
, the program will output:
enter name: Hello bobby bill!
enter favorite color: I like too!
instead of:
enter name: Hello bobby bill!
enter favorite color: I like soft, blue-ish turquoise too!
As I understand it, this is because the bufio.Scanner
that was made in greet()
read all of a.txt
. I can solve this problem easily by making the bufio.Scanner
a global variable and have prompt()
use that instead of creating a new bufio.Scanner
each time, but I am wondering if there is a better way to do this without having to resort to global variables.
答案1
得分: 1
你的分析是正确的,问题在于bufio.Scanner
缓冲了多于一行的文本,所以当你丢弃它时,你就会丢失那部分输入。如果你要使用缓冲输入,你应该确保所有的东西都使用相同的缓冲区,以避免这种问题。
使用全局变量是一种解决方案。另一种解决方案是创建一个类型来保存bufio.Scanner
,并将一些函数转换为方法。
英文:
Your analysis is correct, and the problem is that bufio.Scanner
buffers more than a line of text so when you throw it away you lose that input. If you are going to use buffered input, you should make sure everything uses the same buffer to avoid this sort of problem.
Using a global variable is one solution. Another would be to create a type to hold the bufio.Scanner
and turn some of your functions into methods.
答案2
得分: 1
我认为,由于os.Stdin
是一个全局变量,拥有一个全局缓冲版本是完全合适的。
请注意,Go语言没有真正的全局变量 - 一切都始终在包命名空间中,因此创建一个全局变量并不像在C语言中那样重要。
例如:
package main
import (
"bufio"
"fmt"
"os"
)
// 全局变量
var (
in = bufio.NewScanner(os.Stdin)
)
func prompt(format string) string {
fmt.Print(format)
in.Scan()
return in.Text()
}
func greet() {
name := prompt("请输入姓名:")
fmt.Printf("你好,%s!\n", name)
}
func humor() {
color := prompt("请输入喜欢的颜色:")
fmt.Printf("我也喜欢%s!\n", color)
}
func main() {
greet()
humor()
}
英文:
I would say that since os.Stdin
is a global variable, having a global buffered version of it would be entirely appropriate.
Note that Go doesn't have true global variables - everything is always in a package namespace so making a global variable isn't quite such a big deal as in a language such as C.
Eg
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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论