2011-12-31 61 views
5

我感到困惑this bit of code from the HTTP package轉到功能打字

type HandlerFunc func(ResponseWriter, *Request) 
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { 
    f(w, r) 
} 

爲什麼ServeHTTP方法有,因爲它是類型完全一樣的簽名 - 有什麼意義?

 

測試,我發現如果我通過隨機函數(foo)到HandlerFunc

var bar = HandlerFunc(foo) 

bar成爲HandlerFunc的實例與foo作爲其ServeHTTP方法。現在我真的很困惑這個如何工作。

如果我在一個類型上有多個方法,我怎麼知道哪一個將被附加到新的實例以及什麼名稱或順序?

回答

8

此方法允許您在期望Handler的上下文中使用函數。

會發生什麼事是,有一個Handler接口:

type Handler interface { 
     ServeHTTP(ResponseWriter, *Request) 
    } 

和各種功能都宣佈接受被宣佈屬於這個接口—例如參數:

func TimeoutHandler(h Handler, ns int64, msg string) Handler { 
     f := func() <-chan int64 { 
      return time.After(ns) 
     } 
     return &timeoutHandler{h, f, msg} 
    } 

這是什麼意思當你調用這樣一個函數時,你必須傳入一個屬於這個類型的對象,該類型滿足這個接口,也就是說,一個類型爲ServeHTTP方法與適當的簽名。 (在圍棋,不像某些語言,一種不需要明確實現一個接口,它只是需要有由接口指定的方法)

因此,代碼段,貴公司報價:

type HandlerFunc func(ResponseWriter, *Request) 
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { 
    f(w, r) 
} 

創建一個類型HandlerFunc這是基於func(ResponseWriter, *Request),但增加了一個帶一個名爲ServeHTTP用適當的簽名方法的類型,使之滿足Handler接口。這個ServeHTTP方法只是調用函數本身。所以,如果f是正確的簽名的功能,你可以寫這樣的事情:

var h HandlerFunc = f // h == f, but converted to a HandlerFunc 
         // so it satisfies the Handler interface. 
TimeoutHandler(h, 1000000, "timed out") 

爲了澄清一些事情這一點:

測試,我發現,如果我通過隨機函數(foo)到HandlerFunc

var bar = HandlerFunc(foo)

bar成爲HandlerFunc的實例與foo作爲其ServeHTTP方法。現在我真的很困惑這個如何工作。

首先,它更正確的說,你已經轉換隨機函數foo鍵入HandlerFunc,而不是你已經通過功能HandlerFunc彷彿HandlerFunc是一個功能。 (該HandlerFunc(foo)符號是一個類型轉換,你也可以同樣寫var bar HandlerFunc = foo,讓轉換隱式發生。)

其次,它更正確的說,barServeHTTP方法調用foo,比foo本身實際上ServeHTTP方法。

這有道理嗎?

+0

+1的解釋。功能可以像對象在滿足界面時一樣進行處理,這很酷。 – 2012-01-01 01:09:48

+0

謝謝,這使事情更清晰。 Go是一種非同尋常的語言,但內部,一切都非常簡單。新年快樂btw :)。 – thwd 2012-01-01 04:12:47

+0

@Tom:不客氣,很高興我能幫忙!新年快樂。 :-) – ruakh 2012-01-01 20:06:55