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?

\$\endgroup\$
  • 1
    \$\begingroup\$ Is the file an important side-effect? If so you could do an io.Copy(io.MultiWriter(thefile, otheroutput), input). \$\endgroup\$ – Rafael Feb 18 '15 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\$ – Alex Zylman Feb 20 '15 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\$ – metakeule Apr 15 '15 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\$ – Dave C Aug 22 at 15:47
0
\$\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

\$\endgroup\$
  • 3
    \$\begingroup\$ For a go noob like me: how does this work, why is it better than the solution in the question? \$\endgroup\$ – Vogel612 Jul 27 '18 at 8:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.