Golang 嵌入一个带有额外隐藏方法的接口?

我想http.ResponseWriter在结构中嵌入一个。没关系,它确保我的结构也实现http.ResponseWriter:


type MyWriter struct {

    BytesWritten int

    http.ResponseWriter

}

但是,它不再实现http.Hijacker,http.CloseNotifier或者http.Flusher即使嵌入式http.ResponseWriter通常会实现。


有没有办法做到这一点?


翻过高山走不出你
浏览 157回答 2
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) 的情况的示例,请参阅Gorilla logger。

白衣染霜花

一种解决方案是蛮力解决方案。实际实现所有排列。我试过了,发现它有多痛苦。有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 {&nbsp; &nbsp; HeaderTo(w http.ResponseWriter) http.Header&nbsp; &nbsp; WriteHeaderTo(w http.ResponseWriter, s int)&nbsp; &nbsp; WriteTo(w http.ResponseWriter, b []byte) (n int, err error)&nbsp; &nbsp; // Additional methods that http.ResponseWriter sometimes implements.&nbsp; &nbsp; CloseNotifyTo(w http.CloseNotifier) <-chan bool&nbsp; &nbsp; FlushTo(w http.Flusher)&nbsp; &nbsp; HijackTo(w http.Hijacker) (net.Conn, *bufio.ReadWriter, error)&nbsp; &nbsp; // ReaderFrom is used by the http package to optimize reads from TCP&nbsp; &nbsp; // connections or from files.&nbsp; &nbsp; 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 {&nbsp; &nbsp; rw := &customResponseWriter{base: base, custom: custom}&nbsp; &nbsp; // the base http.ResponseWriter can implement many hidden interfaces,&nbsp; &nbsp; // so check all permutations&nbsp; &nbsp; type HCFR interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(HCFR); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HCFR&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type HCF interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(HCF); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HCF&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type HCR interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(HCR); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HCR&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type HFR interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(HFR); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HFR&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type CFR interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(CFR); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CFR&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type HC interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(HC); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HC&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type HF interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(HF); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HF&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type CF interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(CF); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CF&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type HR interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(HR); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HR&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type CR interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(CR); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CR&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type FR interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(FR); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FR&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type H interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Hijacker&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(H); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; H&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type C interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.CloseNotifier&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(C); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; C&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type F interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; http.Flusher&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(F); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; F&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; type R interface {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; &nbsp; &nbsp; io.ReaderFrom&nbsp; &nbsp; }&nbsp; &nbsp; if _, ok := base.(R); ok {&nbsp; &nbsp; &nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; R&nbsp; &nbsp; &nbsp; &nbsp; }{rw}&nbsp; &nbsp; }&nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; http.ResponseWriter&nbsp; &nbsp; }{rw}}// customResponseWriter allows us to adapt a ResponseWriterTo to a ResponseWriter.type customResponseWriter struct {&nbsp; &nbsp; base&nbsp; &nbsp;http.ResponseWriter&nbsp; &nbsp; custom ResponseWriterTo}func (w *customResponseWriter) Header() http.Header&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ 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)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ w.custom.WriteHeaderTo(w.base, s) }func (w *customResponseWriter) CloseNotify() <-chan bool {&nbsp; &nbsp; 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) {&nbsp; &nbsp; return w.custom.HijackTo(w.base.(http.Hijacker))}func (w *customResponseWriter) ReadFrom(r io.Reader) (n int64, err error) {&nbsp; &nbsp; return w.custom.ReadFromTo(w.base.(io.ReaderFrom), r)}这个想法是将正确的接口嵌入到结构中。然后只暴露“正确”的方法。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go