2

私はGoを初めて使用し(昨日のように)、標準入力からのデータを処理する単純なプログラムをいじっています。私がやりたかったことは、標準入力にデータが提供されない場合、プログラムがヘルプ画面を出力して終了するようにすることでした。私が遭遇した問題は、stdin を介してデータが提供されない場合、プログラムが無期限にハングするように見えることです。プログラムと私の使用目的の短い例を次に示します。

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

入力を提供しない 2 番目のケースは、プログラムがハングする原因です。ドキュメントを読んでも、入力を無期限に待機せず、標準入力に何も存在しない場合にプログラムを中断するようにプログラムをコーディングする方法が明確ではありません。

4

2 に答える 2

4

プログラムは、コードが示すとおりに動作しています。コードは、標準入力から読み取るように指示しています。stdin への入力は、リダイレクトによって提供できます (ご覧のとおり)。またはパイプで。または .... または、ユーザーがキーボードに入力することによって。最後のケースで、人間が何かを入力する前にプログラムが終了するとしたら、非常に驚​​くべきことです。

一般的なアプローチは、(簡略化して)次のようにすることです。

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

すなわち。コマンドライン引数として指定された名前付きファイルを処理できますが、プログラムにファイル名引数が指定されていない場合は、フォールバック/デフォルトで stdin を読み取ります。

このようなアプローチは、シェルスクリプト、パイプを介したコマンドの連鎖などでうまく機能します。

于 2013-08-01T19:41:06.463 に答える
3

特にgoを始めたばかりの場合は、ユースケースにとって少しストレッチになるかもしれませんが、一般的に、タイムアウトのある選択を使用することで、必要な動作を模倣できます。

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: ようこそ、私は言語のように願っています :-)

于 2013-08-02T11:09:03.257 に答える