Alexis Wilke
Alexis Wilke

Reputation: 20818

How do I assign additional ExraFiles using Pipes to have more than one output stream?

I have a command to which I send data through Stdin and expect 28 output streams (including Stdout).

So I wanted to use the cmd.ExtraFiles field with an os.Pipe for each of the os.ExtraFiles.

I wrote the following:

backgroundContext, cancelCommand := context.WithCancel(context.Background())
cmd := exec.CommandContext(backgroundContext, "command", args...)
cmd.ExtraFiles = make([]*io.File, 27, 0)

var outputPipe io.ReadCloser
var inputPipe io.WriteCloser

outputPipe, inputPipe, err = os.Pipe()
cmd.ExtraFiles[0] = &inputPipe
cmd.ExtraFiles[1] = &outputPipe

The last two lines generate an error since the types do not match:

./main.go:876:26: cannot use &inputPipe (type *io.WriteCloser) as type *os.File in assignment
./main.go:877:26: cannot use &outputPipe (type *io.ReadCloser) as type *os.File in assignment

I'm sure we can assign pipes since I can for example use the StdoutPipe() function and it works as expected.

How am I supposed to do that with the os.ExtraFiles?

Upvotes: 1

Views: 164

Answers (1)

Thundercat
Thundercat

Reputation: 121139

The code in the question does not compile because the *os.File values returned from os.Pipe are stored in variables with interfaces types io.ReadCloser and io.WriteCloser. Pointers to values with these types are not assignable to an *os.File.

Fix by assigning the return values to variables with type *os.File.

cmd.ExtraFiles = make([]*os.File, 27)
outputPipe, inputPipe, err := os.Pipe()
if err != nil {
    // handle error
}
cmd.ExtraFiles[0] = inputPipe
cmd.ExtraFiles[1] = outputPipe

Bonus fixes:

  • It's os.File, not io.File.
  • Allocate the slice with length and capacity of 27. It's an error to allocate a slice with capacity less than length.

Upvotes: 1

Related Questions