Hi, I wonder why the two programs below have different behaviors? Both start `yes` command, close write side of the pipe (because the main process doesn't use it), and read from the read side of the pipe. The only difference is one doesn't use goroutine and another uses it.
1) The first program doesn't use goroutine. It works as expected (you'll need to press Ctl-C to temrinate the program).
```
package main
import (
"io"
"os"
"os/exec"
)
func main() {
rpipe, wpipe, err := os.Pipe()
if err != nil {
panic(err)
}
cmd := exec.Command("yes")
cmd.Stdout = wpipe
if err := cmd.Start(); err != nil {
panic(err)
}
wpipe.Close()
if _, err := io.Copy(os.Stdout, rpipe); err != nil {
panic(err)
}
}
```
2) The second program is almost same as the first one, except that it wraps the `yes` command related code in a goroutine. It fails to read data from pipe. The culprit is `wpipe.Close()` line.
```
package main
import (
"io"
"os"
"os/exec"
"fmt"
)
func main() {
rpipe, wpipe, err := os.Pipe()
if err != nil {
panic(err)
}
go func() {
cmd := exec.Command("yes")
cmd.Stdout = wpipe
if err := cmd.Start(); err != nil {
panic(err)
}
}()
// Commenting out this line would make the program works fine. Why?
wpipe.Close()
n, err := io.Copy(os.Stdout, rpipe)
if err != nil {
panic(err)
}
fmt.Printf("n: %d", n)
}
// Output:
// n: 0
```
Question 1: I wonder why the above code doesn't work?
I find two ways to make it work:
1) Remove `wpipe.Close()` line. I don't like this approach because I think it's a convention in Unix programs to close unused file descriptors.
2) Move `wpipe.Close()` to the goroutine. Question 2: Why does this work?
Thanks for any explanation.