2

我是 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)
    }
}


Running with input:
go run test.go < lines.txt
line1
line2
line3


Running with no input:
go run test.go

我不提供输入的第二种情况是导致程序挂起的原因。通读文档,我不清楚如何编写程序以不无限期地等待输入,而是在标准输入上没有任何内容时中断。

4

2 回答 2

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

IE。允许处理作为命令行参数给出的命名文件 - 但当程序没有文件名参数时回退/默认读取标准输入。

这种方法与 shell 脚本、通过管道链接命令等很好地配合。

于 2013-08-01T19:41:06.463 回答
3

对于您的用例来说,这可能有点牵强,特别是如果您刚开始使用 go,但通常可以通过使用带有超时的 select 来模仿您想要的行为:

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

将其视为您下一个学习步骤的灵感。

PS: Wellcome to go,我希望喜欢这种语言:-)

于 2013-08-02T11:09:03.257 回答