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 foo
gõ HandlerFunc
, 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ế là phương thức ServeHTTP
.
Điều đó có hợp lý không?
+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. –
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
@Tom: Bạn được chào đón, vui vì tôi có thể giúp! Chúc mừng năm mới. :-) – ruakh