英文:
file input in golang
问题
我对Go语言还很陌生(就是在过去的一天内),正在尝试编写一个简单的程序,用于处理来自标准输入的数据。我想要的是,如果没有提供任何数据给标准输入,程序会输出一个帮助界面然后退出。但是问题是,当没有通过标准输入提供数据时,程序似乎会无限期地挂起。这是一个程序的简短示例和我的预期用法:
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
str := scanner.Text()
fmt.Println(str)
}
}
使用输入运行:
go run test.go < lines.txt
line1
line2
line3
使用无输入运行:
go run test.go
当我没有提供输入时,第二种情况会导致程序挂起。阅读文档后,我不清楚如何编写程序以使其不会无限期地等待输入,而是在标准输入上没有内容时中断。
英文:
I'm brand new to Go (as in within the last day) and am playing around with a simple program which processes data from stdin. What I wanted to do was to make it such that if no data were provided to stdin then the program would output a help screen and then exit. The problem I've run into is that the program seems to hang indefinitely when no data is provided via stdin. Here is a short example of the program and my intended usage:
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
str := scanner.Text()
fmt.Println(str)
}
}
Running with input:
go run test.go < lines.txt
line1
line2
line3
Running with no input:
go run test.go
The second case where I do not provide input is what causes the program to hang. Reading through the docs it is not clear to me how I would be able to code the program to not wait for input indefinitely, but rather break if nothing is present on stdin.
答案1
得分: 4
程序的行为完全按照代码所说的那样。代码要求从标准输入读取。可以通过重定向(如你所示)或通过管道来提供标准输入。或者通过用户键盘输入。如果在最后一种情况下,程序在用户输入之前退出,那将是非常令人惊讶的。
一种常见的方法是像下面这样做(简化版):
var in *os.File
var err error
switch name := flag.Arg(0); {
case name == "":
in = os.Stdin
default:
if in, err = os.Open(name); err != nil {
log.Fatal(err)
}
}
也就是说,允许在命令行参数中指定一个文件名进行处理,但当没有文件名参数传递给程序时,默认读取标准输入。
这种方法与shell脚本、通过管道链接命令等非常搭配。
英文:
The program is behaving exactly as the code says. The code says to read from stdin. Input to stdin can be provided by redirection (as you show). Or by piping. Or .... Or by user typing to the keyboard. It would be very surprising if in the last case the program would exit before the human can enter something.
A common approach is to do something like (simplified):
var in *os.File
var err error
switch name := flag.Arg(0); {
case name == "":
in = os.Stdin
default:
if in, err = os.Open(name); err != nil {
log.Fatal(err)
}
}
Ie. allow to process a named file given as the command line argument - but fallback/default to reading stdin when no file name argument is given to the program.
Such approach plays nicely with shell scripting, chaining commands through pipes, etc.
答案2
得分: 3
func scanForInput() chan string{
lines := make(chan string)
go func(){
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
lines <- scanner.Text()
}
close(lines)
}
return lines
}
func main(){
lines := scanForInput()
for {
select{
case line, closed := <- lines:
fmt.Prinln(line)
if closed {
return
}
case time.After(1 * time.Second):
printHelpMessage()
return
}
}
}
英文:
It might be a bit of a strech for your usecase especially if you just picked up go, but in general the behaviour you want could be mimiced by using a select with a timeout:
func scanForInput() chan string{
lines := make(chan string)
go func(){
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
lines <- scanner.Text()
}
close(lines)
}
return lines
}
func main(){
lines := scanForInput()
for {
select{
case line, closed := <- lines:
fmt.Prinln(line)
if closed {
return
}
case time.After(1 * time.Second):
printHelpMessage()
return
}
}
}
Consider it an inspiration for your next learning step.
PS: Wellcome to go, I hope like the language
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论