Home > Mobile >  How to create an interface by combining interfaces from different packages?
How to create an interface by combining interfaces from different packages?

Time:07-23

Situation

For code base I am using pion/rtpio package.

I am trying to extend the interface RTPwriter by adding a Close() function to it. The goal is to make a NewRTPWritCloser() function that return a writeCloser with the combined functions.

From the package, I see the author already created the interface RTPWriteCloser

type RTPWriteCloser interface {
    RTPWriter
    io.Closer
}

Attempt

I made this to reuse the function, which is wrong but I didn't know the alternative yet:


func NewRTPWriteCloser(wc io.WriteCloser) rtpio.RTPWriteCloser {
    writeCloser := rtpio.NewRTPWriter(wc)
    return writeCloser
}

and expected that the wc have its own Close() function ready, so the returned writeCloser will satisfy the interface RTPWriteCloser. However, I got (missing method Close) as an error.

The function NewRTPWriter() is like this:

func NewRTPWriter(w io.Writer) RTPWriter {
    return &RawRTPWriter{
        dst: w,
    }
}

Questions

  • How do we create an instance with all desired functions from multiple embedded interfaces at the same time to satisfy the embedding interface ?
  • In this example, we want to create NewRTPWriteCloser function for RTPWriteCloser interface, but we can not create first a writer then add Close function to it ?
  • Do I have to create a struct of RTPWriteCloser and rewrite all necessary functions that take in that struct ? (seems inefficient)

Searched

I did my own searching for example: interfaces inside interface and combining or extending interfaces, but they don't get me to the end to understand my problem.

CodePudding user response:

I believe you will need to create a new struct as you suggest to implement your interface, let's call it RawRTPWriterCloser and add the implementation for Close().

You can embed structs in other structs however, so the Close() method is the only function you'll need to additionally define:

type RawRTPWriterCloser struct {
    rtpio.RawRTPWriter
}

func (rw *RawRTPWriterCloser) Close() error {
    panic("add implementation here")
}

CodePudding user response:

You should define a adapter struct, adding the io.Closer semantics to your base type:

type WrappingRTPWriteCloser struct {
    w RTPWriter
    c io.Closer
}

You should then define the Close method to satisfy the interface:

func (w *WrappingRTPWriteCloser) Close() error {
    return w.c.Close()
}

Then you should create a new reference of your wrapping struct, upon an instance creation:

func NewRTPWriteCloser(wc io.WriteCloser) rtpio.RTPWriteCloser {
    writeCloser := WrappingRTPWriteCloser{
            w: rtpio.NewRTPWriter(wc),
            c: wd,
    }
    return writeCloser
}

An alternative solution, would be to use the RTPPipe function provided out of the box by the package and which returns both an RTPReadCloser and a RTPWriteCloser instance (piping the RTPReadCloser input to the RTPWriteCloser output):

// RTPPipe creates a new RTPPipe and returns the reader and writer.
func RTPPipe() (RTPReadCloser, RTPWriteCloser) {
    r, w := io.Pipe()
    return &pipeRTPReader{closer: r, rtpReader: NewRTPReader(r, 1500)}, &pipeRTPWriter{closer: w, rtpWriter: NewRTPWriter(w)}
}
  • Related