LoginSignup
1
0

More than 3 years have passed since last update.

Windows の Go で stdin に書きつつ外部プログラムを起動するとハマる

Posted at

標準入力からデータを受け取るようなプログラムを起動させようとして、stdin に WriteString したらハマりになったので対処法をメモしておきます。

ProtocolBuffer のプラグイン書いてて踏みましたが、Go の周辺ツールとかカスタムしようとすると同じ感じで踏むかもしれません。

Windows で 4KB 以上のデータを書き込んだ場合にのみ発生し、4KB 以下の場合や Windows 以外の OS の場合は発生しません。

例えばこんなコード。

func main() {
    content, _ := ioutil.ReadFile("test.txt") // 適当に 4KB 以上のテキスト

    c := exec.Command("more")
    stdin, _ := c.StdinPipe()

    io.WriteString(stdin, string(content)) // ここで返ってこない

    stdin.Close()
}

恐らく、パイプのバッファが足りなくなって、空くのを待っているけれども、
書き込みが終わってないのでプログラムが起動せず、空ける人がいないという状況と思われる。

以下のようにしたら、とりあえず動いた。

func main() {
    content, _ := ioutil.ReadFile("test.txt") // 適当に 4KB 以上のテキスト

    c := exec.Command("more")
    stdin, _ := c.StdinPipe()

    go func() {
        defer stdin.Close()
        io.WriteString(stdin, string(content))
    }()

    output, _ := c.CombinedOutput()
    fmt.Print(string(output))
}
1
0
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0