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。
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)
}
这个想法是将正确的接口嵌入到结构中。然后只暴露“正确”的方法。
- 2 回答
- 0 关注
- 156 浏览
添加回答
举报