2015-12-22 82 views
1

我想在結構中嵌入一個http.ResponseWriter。這很好,這讓我的肯定也是結構實現http.ResponseWriterGolang用額外的隱藏方法嵌入了一個接口?

type MyWriter struct { 
    BytesWritten int 
    http.ResponseWriter 
} 

然而,它不再執行http.Hijackerhttp.CloseNotifierhttp.Flusher即使嵌入式http.ResponseWriter通常不會。

有沒有辦法做到這一點?

回答

2

如果您知道響應作家滿足所有問題中列出的接口,那麼你可以這樣做:

type allResponseWriterInterfaces { 
    http.ResponseWriter 
    http.Hijacker 
    http.CloseNotifier 
    http.Flusher 
} 

type MyWriter struct { 
    BytesWritten int 
    allResponseWriterInterfaces 
} 

... 

aw, ok := w.(allResponseWriterInterfaces) 
if !ok { 
    // oops, response writer does not implement the interfaces 
    // handle the error 
} 
mw := MyWriter{0, aw} 

如果響應作家不滿足所有接口的它得到的混亂。有關處理響應寫入程序滿足(http.ResponseWriter,http.CloseNotifier)或(http.ResponseWriter,http.CloseNotifier,http.Hijacker)的情況的示例,請參閱the Gorilla logger

+0

是的,我的執行開始看起來很混亂。除了我也試圖有選擇地滿足http.flusher,使8個排列而不是4.我剛纔看到http.ResponseWriter有時也實現了io.ReaderFrom,使16個排列? – chowey

+0

如何編寫[go generate](https://blog.golang.org/generate)程序來編寫所有排列的代碼!儘管如此,我希望有人用簡單的解決方案來回答。 –

0

一個解決方案是蠻力解決方案。實際上實施所有排列。我試過這個,發現它有多痛苦。有18個排列組合!

所以這裏是一個通用的包裝。好處是你可以多次重複使用這個包裝。

的關鍵是定義像這樣的接口:

// ResponseWriterTo can proxy requests to an underlying http.ResponseWriter. 
// It is used with CustomResponseWriter to wrap an http.ResponseWriter with 
// custom behavior. 
type ResponseWriterTo interface { 
    HeaderTo(w http.ResponseWriter) http.Header 
    WriteHeaderTo(w http.ResponseWriter, s int) 
    WriteTo(w http.ResponseWriter, b []byte) (n int, err error) 

    // Additional methods that http.ResponseWriter sometimes implements. 
    CloseNotifyTo(w http.CloseNotifier) <-chan bool 
    FlushTo(w http.Flusher) 
    HijackTo(w http.Hijacker) (net.Conn, *bufio.ReadWriter, error) 

    // ReaderFrom is used by the http package to optimize reads from TCP 
    // connections or from files. 
    ReadFromTo(w io.ReaderFrom, r io.Reader) (n int64, err error) 
} 

,這樣我們可以定義一個定製的包裝功能(這是冗長的部分):

// CustomResponseWriter creates a http.ResponseWriter that implements as many 
// hidden interfaces from the base http.ResponseWriter as are available. 
func CustomResponseWriter(base http.ResponseWriter, custom ResponseWriterTo) http.ResponseWriter { 
    rw := &customResponseWriter{base: base, custom: custom} 

    // the base http.ResponseWriter can implement many hidden interfaces, 
    // so check all permutations 

    type HCFR interface { 
     http.ResponseWriter 
     http.Hijacker 
     http.CloseNotifier 
     http.Flusher 
     io.ReaderFrom 
    } 
    if _, ok := base.(HCFR); ok { 
     return struct { 
      HCFR 
     }{rw} 
    } 

    type HCF interface { 
     http.ResponseWriter 
     http.Hijacker 
     http.CloseNotifier 
     http.Flusher 
    } 
    if _, ok := base.(HCF); ok { 
     return struct { 
      HCF 
     }{rw} 
    } 

    type HCR interface { 
     http.ResponseWriter 
     http.Hijacker 
     http.CloseNotifier 
     io.ReaderFrom 
    } 
    if _, ok := base.(HCR); ok { 
     return struct { 
      HCR 
     }{rw} 
    } 

    type HFR interface { 
     http.ResponseWriter 
     http.Hijacker 
     http.Flusher 
     io.ReaderFrom 
    } 
    if _, ok := base.(HFR); ok { 
     return struct { 
      HFR 
     }{rw} 
    } 

    type CFR interface { 
     http.ResponseWriter 
     http.CloseNotifier 
     http.Flusher 
     io.ReaderFrom 
    } 
    if _, ok := base.(CFR); ok { 
     return struct { 
      CFR 
     }{rw} 
    } 

    type HC interface { 
     http.ResponseWriter 
     http.Hijacker 
     http.CloseNotifier 
    } 
    if _, ok := base.(HC); ok { 
     return struct { 
      HC 
     }{rw} 
    } 

    type HF interface { 
     http.ResponseWriter 
     http.Hijacker 
     http.Flusher 
    } 
    if _, ok := base.(HF); ok { 
     return struct { 
      HF 
     }{rw} 
    } 

    type CF interface { 
     http.ResponseWriter 
     http.CloseNotifier 
     http.Flusher 
    } 
    if _, ok := base.(CF); ok { 
     return struct { 
      CF 
     }{rw} 
    } 

    type HR interface { 
     http.ResponseWriter 
     http.Hijacker 
     io.ReaderFrom 
    } 
    if _, ok := base.(HR); ok { 
     return struct { 
      HR 
     }{rw} 
    } 

    type CR interface { 
     http.ResponseWriter 
     http.CloseNotifier 
     io.ReaderFrom 
    } 
    if _, ok := base.(CR); ok { 
     return struct { 
      CR 
     }{rw} 
    } 

    type FR interface { 
     http.ResponseWriter 
     http.Flusher 
     io.ReaderFrom 
    } 
    if _, ok := base.(FR); ok { 
     return struct { 
      FR 
     }{rw} 
    } 

    type H interface { 
     http.ResponseWriter 
     http.Hijacker 
    } 
    if _, ok := base.(H); ok { 
     return struct { 
      H 
     }{rw} 
    } 

    type C interface { 
     http.ResponseWriter 
     http.CloseNotifier 
    } 
    if _, ok := base.(C); ok { 
     return struct { 
      C 
     }{rw} 
    } 

    type F interface { 
     http.ResponseWriter 
     http.Flusher 
    } 
    if _, ok := base.(F); ok { 
     return struct { 
      F 
     }{rw} 
    } 

    type R interface { 
     http.ResponseWriter 
     io.ReaderFrom 
    } 
    if _, ok := base.(R); ok { 
     return struct { 
      R 
     }{rw} 
    } 

    return struct { 
     http.ResponseWriter 
    }{rw} 
} 

// customResponseWriter allows us to adapt a ResponseWriterTo to a ResponseWriter. 
type customResponseWriter struct { 
    base http.ResponseWriter 
    custom ResponseWriterTo 
} 

func (w *customResponseWriter) Header() http.Header   { return w.custom.HeaderTo(w.base) } 
func (w *customResponseWriter) Write(b []byte) (int, error) { return w.custom.WriteTo(w.base, b) } 
func (w *customResponseWriter) WriteHeader(s int)   { w.custom.WriteHeaderTo(w.base, s) } 
func (w *customResponseWriter) CloseNotify() <-chan bool { 
    return w.custom.CloseNotifyTo(w.base.(http.CloseNotifier)) 
} 
func (w *customResponseWriter) Flush() { w.custom.FlushTo(w.base.(http.Flusher)) } 
func (w *customResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { 
    return w.custom.HijackTo(w.base.(http.Hijacker)) 
} 
func (w *customResponseWriter) ReadFrom(r io.Reader) (n int64, err error) { 
    return w.custom.ReadFromTo(w.base.(io.ReaderFrom), r) 
} 

的想法是嵌入將正確的接口轉換爲結構體。那麼只有「正確的」方法纔會暴露。

相關問題