4
\$\begingroup\$

I was looking for a way to write to and then read from a file in different parts of my code, without passing the filename around and without consumers needing to know it was coming from a file.

I came up with this FilePipe based on io.Pipe:

package pipe
import (
 "io"
 "os"
)
func FilePipe(name string) (*io.PipeReader, *io.PipeWriter) {
 inr, inw := io.Pipe()
 outr, outw := io.Pipe()
 go func() {
 // Open the file for writing
 f, err := os.Create(name)
 if err != nil {
 outw.CloseWithError(err)
 return
 }
 // Copy the input to the file
 _, err = io.Copy(f, inr)
 f.Close()
 if err != nil {
 outw.CloseWithError(err)
 return
 }
 // Open the file for reading
 f, err = os.Open(name)
 if err != nil {
 outw.CloseWithError(err)
 return
 }
 // Copy the file to the output
 _, err = io.Copy(outw, f)
 f.Close()
 if err != nil {
 outw.CloseWithError(err)
 return
 }
 outw.Close()
 }()
 return outr, inw
}

What do you think? Is there a better way to do this?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Feb 18, 2015 at 4:05
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Is the file an important side-effect? If so you could do an io.Copy(io.MultiWriter(thefile, otheroutput), input). \$\endgroup\$ Commented Feb 18, 2015 at 21:40
  • \$\begingroup\$ Yeah, in this case it is an important side-effect. We don't want to start processing the results until we've finished writing everything to the file successfully. \$\endgroup\$ Commented Feb 20, 2015 at 3:03
  • \$\begingroup\$ Please provide a full example with a caller of FilePipe and explain what exactly your code should do and how you want to avoid races. I see no mutex or channel, so I can't see how this could work nor how you want it to work. \$\endgroup\$ Commented Apr 15, 2015 at 4:44
  • \$\begingroup\$ You should always check the error return by os.File.Close if the file was written to. An error writing a file may not get reported until the file gets closed. \$\endgroup\$ Commented Aug 22, 2019 at 15:47

1 Answer 1

1
\$\begingroup\$

you could use a teereader:

inr, inw := io.Pipe()
f, _ := os.Create(name)
tr := io.TeeReader(inr, f)
return tr, inw

use this code in go routine and handle errors

Vogel612
25.5k7 gold badges59 silver badges141 bronze badges
answered Jul 27, 2018 at 7:22
\$\endgroup\$
1
  • 3
    \$\begingroup\$ For a go noob like me: how does this work, why is it better than the solution in the question? \$\endgroup\$ Commented Jul 27, 2018 at 8:46

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.