为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
翻过高山走不出你 2021-11-29 16:56:38
我想http.ResponseWriter在结构中嵌入一个。没关系,它确保我的结构也实现http.ResponseWriter:type MyWriter struct {    BytesWritten int    http.ResponseWriter}但是,它不再实现http.Hijacker,http.CloseNotifier或者http.Flusher即使嵌入式http.ResponseWriter通常会实现。有没有办法做到这一点?
查看完整描述

2 回答

?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

如果您知道响应编写器满足问题中列出的所有接口,那么您可以执行以下操作:


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。


查看完整回答
反对 回复 2021-11-29
?
白衣染霜花

TA贡献1796条经验 获得超10个赞

一种解决方案是蛮力解决方案。实际实现所有排列。我试过了,发现它有多痛苦。有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)

}

这个想法是将正确的接口嵌入到结构中。然后只暴露“正确”的方法。


查看完整回答
反对 回复 2021-11-29
  • 2 回答
  • 0 关注
  • 156 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信