2011-12-31 32 views
5

tôi là nhầm lẫn về this bit of code from the HTTP package:Go chức năng gõ

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

Tại sao phương pháp ServeHTTP có chữ ký chính xác giống như nó là loại - điểm là gì?

 

kiểm tra, tôi phát hiện ra rằng nếu tôi vượt qua một hàm ngẫu nhiên (foo) đến HandlerFunc:

var bar = HandlerFunc(foo) 

bar trở thành một thể hiện của HandlerFunc với foo như phương pháp ServeHTTP của nó. Bây giờ tôi thực sự bối rối về cách hoạt động của nó.

Nếu tôi có nhiều phương pháp trên một loại, làm thế nào để tôi biết cái nào sẽ được gắn vào cá thể mới và với tên hoặc thứ tự nào?

Trả lời

8

Cách tiếp cận này cho phép bạn sử dụng hàm trong ngữ cảnh mong đợi một Handler.

gì xảy ra được, có một giao diện Handler:

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

và nhiều chức năng được khai báo để chấp nhận các thông số được tuyên bố thuộc về giao diện này — ví dụ:

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

Điều này có nghĩa là là khi bạn gọi một hàm như vậy, bạn phải truyền vào một đối tượng thuộc loại mà thỏa mãn giao diện này, có nghĩa là, một loại có ServeHTTP phương pháp có chữ ký thích hợp. (. Trong Go, không giống như một số ngôn ngữ, một loại không cần phải thực hiện một cách rõ ràng một giao diện, nó chỉ cần có phương pháp theo quy định của giao diện)

Vì vậy, mã-đoạn mà bạn trích dẫn:

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

tạo kiểu HandlerFunc dựa trên func(ResponseWriter, *Request), nhưng tăng thêm loại có phương thức được gọi là ServeHTTP có chữ ký thích hợp để nó đáp ứng giao diện Handler. Phương thức ServeHTTP này chỉ gọi chính hàm đó. Vì vậy, nếu f là một chức năng với chữ ký đúng, bạn có thể viết một cái gì đó như thế này:

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

Để làm rõ một vài điều về vấn đề này:

kiểm tra, tôi phát hiện ra rằng nếu tôi vượt qua một ngẫu nhiên chức năng (foo) đến HandlerFunc:

var bar = HandlerFunc(foo)

bar trở thành một thể hiện của HandlerFunc với foo như nó ServeHTTP phương pháp. Bây giờ tôi thực sự bối rối về cách hoạt động của nó.

Thứ nhất, đó là chính xác hơn để nói rằng bạn đã chuyển một hàm ngẫu nhiên fooHandlerFunc, chứ không phải là bạn đã qua chức năng -HandlerFunc như thể là một HandlerFunc chức năng. (Ký hiệu HandlerFunc(foo) là một thợ đúc chư, bạn có thể chỉ cần cũng viết var bar HandlerFunc = foo và để cho các chuyển đổi xảy ra ngầm.)

Thứ hai, đó là chính xác hơn để nói rằng bar có một phương pháp ServeHTTP rằng gọifoo, hơn thế foo bản thân trên thực tế phương thức ServeHTTP.

Điều đó có hợp lý không?

+0

+1 để giải thích. Thật tuyệt khi các chức năng có thể được xử lý theo cách tương tự như các đối tượng có thể khi nói đến các giao diện thỏa mãn. –

+0

Cảm ơn bạn, điều này làm cho mọi thứ rõ ràng hơn rất nhiều. Go thực sự là một ngôn ngữ bất thường nhưng bên trong, mọi thứ đều rất đơn giản. Chúc mừng năm mới btw :). – thwd

+0

@Tom: Bạn được chào đón, vui vì tôi có thể giúp! Chúc mừng năm mới. :-) – ruakh

Các vấn đề liên quan