2015-02-09 136 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