检查Golang中STDIN上是否有要读取的内容

时间:2014-03-30 13:18:10

标签: go

如果某个字符串通过管道连接到其STDIN,我需要一个命令行实用程序来表现不同。这是一些最小的例子:

package main // file test.go

import (
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    bytes, _ := ioutil.ReadAll(os.Stdin)

    if len(bytes) > 0 {
        fmt.Println("Something on STDIN: " + string(bytes))
    } else {
        fmt.Println("Nothing on STDIN")
    }
}

如果您这样称呼它可以正常工作:

echo foo | go run test.go

如果在STDIN上没有任何内容的情况下调用test.go,那么事情就会停留在......

bytes, _ := ioutil.ReadAll(os.Stdin)

......等待EOF

我需要做些什么才能实现这一目标?

提前致谢!

4 个答案:

答案 0 :(得分:37)

我通过使用os.ModeCharDevice:

解决了这个问题
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
    fmt.Println("data is being piped to stdin")
} else {
    fmt.Println("stdin is from a terminal")
}

答案 1 :(得分:13)

使用IsTerminal中的code.google.com/p/go.crypto/ssh/terminal功能(exp/terminal)或Isatty中的github.com/andrew-d/go-termutil功能  这是一个更受关注的方案。

如果stdin是终端/ tty,那么你就不是管道式的东西而且你可以做些不同的事情。

这是一个例子

package main

import (
    "fmt"
    "github.com/andrew-d/go-termutil"
    "io"
    "os"
)

func main() {
    if termutil.Isatty(os.Stdin.Fd()) {
        fmt.Println("Nothing on STDIN")
    } else {
        fmt.Println("Something on STDIN")
        io.Copy(os.Stdout, os.Stdin)
    }
}

测试

$ ./isatty 
Nothing on STDIN
$ echo "hello" | ./isatty 
Something on STDIN
hello
$ (sleep 1 ; echo "hello") | ./isatty 
Something on STDIN
hello

答案 2 :(得分:2)

如果上述方法都不适合您,请尝试以下方式:

stat, err := os.Stdin.Stat()
if err != nil {
    return nil, fmt.Errorf("you have an error in stdin:%s", err)
}
if (stat.Mode() & os.ModeNamedPipe) == 0 {
    return nil, errors.New("you should pass smth to stdin")
}

它在darwin(Mac OS)和linux(Ubuntu)中都适用于我。

答案 3 :(得分:0)

这样做:

package main // file test.go

import (
    "bufio"
"fmt"
    "os"
)

func main() {
    in := bufio.NewReader(os.Stdin)
    stats, err := os.Stdin.Stat()
    if err != nil {
        fmt.Println("file.Stat()", err)
    }

    if stats.Size() > 0 {
        in, _, err := in.ReadLine()
        if err != nil {
            fmt.Println("reader.ReadLine()", err)
        }
        fmt.Println("Something on STDIN: " + string(in))
    } else {
        fmt.Println("Nothing on STDIN")
    }
}

谢谢@Kluyg!