On Sat, Feb 27, 2021 at 7:03 PM Deiter <hwaterf...@gmail.com> wrote: > > Go: go1.15.8 darwin/amd64 > OS: MacOS 11.2.1 > > It makes sense to me that a function can have arguments that are interfaces - > so long as the argument provides the methods that the function requires, it > will be happy. However, I’m having a difficult time understanding functions > that return an interface. I posted code here for context. Note that I’m not > concerned about the deadlock that occurs in the playground - it works fine on > my Mac. > > The code comes from the example provided in the Cmd.StdoutPipe documentation, > which indicates: > func (c *Cmd) StdoutPipe() (io.ReadCloser, error) > > The example uses a “short assignment” statement, so it’s not obvious what > “concrete” type c.StdoutPipe() returns, but according to the io.ReadCloser > documentation, it will have to provide these methods: > type ReadCloser interface { > Reader > Closer > } > > My (clearly flawed) interpretation of interface types suggested that I could > assign the first result from c.StdoutPipe() to anything that implements > io.ReadCloser. The io.PipeReader documentation indicates that it provides > both a Read() and a Close() function with the appropriate signatures, so I > figured I’d try connecting up both ends of a pipe: > > rPipe, _ := io.Pipe() > p, err := cmd.StdoutPipe() > if err != nil { > log.Fatal(err) > } > rPipe = p > > The first clue that I was misguided was when the compiler indicated that I > needed a type assertion. I put one in to see what would happen: > rPipe = p.(*io.PipeReader) > > Everything compiled, but not surprising, it panics: > panic: interface conversion: io.ReadCloser is *os.File, not *io.PipeReader > > I suppose it makes sense that an assignment operator requires more than > simply interface compatibility. A couple of questions: > > How is one supposed to know what type is required in a situation like this? > Is a type assertion panic the only way to discover that a *os.File type is > required?!
The general expectation is that you will store the first result of StdoutPipe in a variable of type io.ReadCloser. Then you would call Read and Close methods on that value as appropriate. You are not expected to store the result in a variable of type *os.File, and in particular there is no guarantee that future releases of Go will continue returning a *os.File from StdoutPIpe. > Any suggestions on how I can get a io.PipeReader to connect with the > cmd.StdoutPipe()? I don't understand why you would want to do this. You could start a goroutine that calls io.Copy from the cmd.StdoutPipe result to the PipeWriter returned by io.Pipe, and then you could read from the PipeReader, but that seems pointless. Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXa5_J6EWEUFmEm%3DffanhEEjww9x2jku%2BMXZ3gmEFOsdQ%40mail.gmail.com.