一個解決方案是蠻力解決方案。實際上實施所有排列。我試過這個,發現它有多痛苦。有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)
}
的想法是嵌入將正確的接口轉換爲結構體。那麼只有「正確的」方法纔會暴露。
是的,我的執行開始看起來很混亂。除了我也試圖有選擇地滿足http.flusher,使8個排列而不是4.我剛纔看到http.ResponseWriter有時也實現了io.ReaderFrom,使16個排列? – chowey
如何編寫[go generate](https://blog.golang.org/generate)程序來編寫所有排列的代碼!儘管如此,我希望有人用簡單的解決方案來回答。 –