我想在结构中嵌入http.ResponseWriter
。没关系,它确保我的结构也实现http.ResponseWriter
:
type MyWriter struct {
BytesWritten int
http.ResponseWriter
}
但是,它不再实现http.Hijacker
,http.CloseNotifier
或http.Flusher
,即使嵌入式http.ResponseWriter
通常也是如此。
有没有办法做到这一点?
答案 0 :(得分: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。
答案 1 :(得分: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)
}
我们的想法是将正确的接口嵌入到结构中。那么只有&#34;对&#34;方法暴露。