Program should be able to get input from stdin
on terminal, as follows:
echo foobar | program
However, in the source below for Program, the stdin
read blocks if the pipe is omitted:
package main
import (
"fmt"
"os"
)
func main() {
b := make([]byte, 1024)
r := os.Stdin
n, e := r.Read(b)
if e != nil {
fmt.Printf("Err: %s
", e)
}
fmt.Printf("Res: %s (%d)
", b, n)
}
So how can Program detect whether something is being piped to it in this manner, and continue execution instead of blocking if not?
... and is it a good idea to do so?
os.Stdin
is treated like a file and has permissions. When os.Stdin
is open, the perms are 0600
, when closed it's 0620
.
This code works:
package main
import (
"fmt"
"os"
)
func main() {
stat, _ := os.Stdin.Stat()
fmt.Printf("stdin mode: %v
", stat.Mode().Perm())
if stat.Mode().Perm() == 0600 {
fmt.Printf("stdin open
")
return
}
fmt.Printf("stdin close
")
}
It would be possible if you put the read in a goroutine and use select to do a non-blocking read from the channel in main, but you would then have a race condition where you could get different results depending on whether the data comes in quickly enough. What is the larger problem you're trying to solve?