如何实现接口的方法覆盖

I wrote a tool which wraps http.ResponseWriter and supplies a new method to render a template.

 type MyResponseWriter interface {
      http.ResponseWriter
      Render(tmpl string, v interface{}
 }
 type myResponseWriter struct {
     server *Server
     http.ResponseWriter
 }

 func (rw *myResponseWriter) Render(tmpl string, v interface{}) {
      rw.server.Render(rw, tmpl, v)
 }

Now, I want to override MyResponseWriter's Write method to enable gzip compression as a pluggable filter without knowing the implementation of MyResponseWriter.

I wrote a GzipResponseWriter here, and it's used as an MyResponseWriter, so it's pluggable:

type GzipResponseWriter struct {
     MyResponseWriter
}

func (grw *GzipResponseWriter) Write(data []byte) (int, error) {
      return GzipWrite(grw.MyResponseWriter, data)       
}

But, when I enable GzipResponseWriter then call Render, it still calls the MyResponseWriter's Write, rather than GzipResponseWriter, and the browser show me an "Content Encoding Error".

That's all because of when I call Render of a GzipResponseWriter, the real method receiver is still the myResponseWriter, and Render calls myResponseWriter's Write.

I think it's a common requirement that we make changes on some methods of a interface that libraries/frameworks supplied, then other methods of this interface will call these new methods rather than old methods. In my question, the requirement is gzip compression, but this feature is so difficult to implement in Go.

Is there a solution to implements this proposal? Thanks.

Add a new field out io.Writer to the myResponseWriter, and also add the io.Write() method which uses this out field:

type myResponseWriter struct {
    out io.Writer
    server *Server
    http.ResponseWriter
}

func (m *myResponseWriter) Write(b []byte) (int, error) {
    return m.out.Write(b)
}

And by default set the same http.ResponseWriter to the out field too.

And when you want to switch to Gzipped response, simply wrap the out writer like this:

out = gzip.NewWriter(out)

Since myResponseWriter.Write() uses the out field, your Render() method will send its output through the gzip writer.