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 forRTPWriteCloser
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)}
}