2015-02-09 130 views
1

我写了一个工具,它包装了http.ResponseWriter并提供了一种新的方法来渲染模板。如何实现方法覆盖接口

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

现在,我要重写MyResponseWriterWrite方法来启用gzip压缩,作为一个可插入过滤器不知道的MyResponseWriter实施。

我写了一个GzipResponseWriter这里,并且它用作MyResponseWriter,所以它的可插拔:

type GzipResponseWriter struct { 
    MyResponseWriter 
} 

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

但是,当我让GzipResponseWriter然后调用Render,它仍然会调用MyResponseWriterWrite,而不是GzipResponseWriter , 和浏览器显示“内容编码错误”。

这时候,我所说的GzipResponseWriterRender的一切,因为,真正的方法接收器仍是myResponseWriter,并Render电话myResponseWriterWrite

我认为这是一个常见的需求,我们对库/框架提供的接口的某些方法进行了更改,然后此接口的其他方法将调用这些新方法而不是旧方法。在我的问题中,需求是gzip压缩,但这个特性在Go中很难实现。

是否有解决方案来实现此提议? 谢谢。

+0

我假设你想写'类型GzipResponseWriter接口{'(缺少'interface'关键字)... – icza 2015-02-09 12:22:43

+0

谢谢。这是一个结构。 – cosiner 2015-02-09 12:28:11

+0

那么,这改变了图片,我不得不重写我的答案。 – icza 2015-02-09 12:36:20

回答

0

添加一个新的领域out io.WritermyResponseWriter,并且还添加io.Write()方法使用这种out领域:

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

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

,并默认设置相同http.ResponseWriterout场了。

而当你想切换到Gzip压缩的响应,只是包裹out作家是这样的:

out = gzip.NewWriter(out) 

由于myResponseWriter.Write()使用out场,你Render()方法将通过gzip的作家发送它的输出。

+0

但是,如果我在调用'Write'的'myGzipResponseWriter'上调用'Render',真正的'Write'方法接收者仍然是'myResonseWriter',而不是'myGzipResonseWriter',所以'GzipWrite'不会被调用。 – cosiner 2015-02-09 12:37:26

+0

对不起,它仍然不是我想要的,如果我想启用gzip,我必须为'MyResponseWriter'界面添加一个改变'out'字段的方法。 – cosiner 2015-02-09 13:28:25