Cú pháp khai báo hàm: những thứ trong ngoặc đơn trước tên hàm


248

Tôi xin lỗi tôi không thể cụ thể hơn trong tiêu đề câu hỏi, nhưng tôi đang đọc một số mã Go và tôi đã gặp các khai báo hàm của mẫu này:

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    ...
}

từ https://github.com/matter most / pl platform / blob / master / api / content.go

func (s *GracefulServer) BlockingClose() bool {
    ...
}

từ https://github.com/braintree/manners/blob/master/server.go

Không (h handler)(s *GracefulServer)giữa các dấu ngoặc đơn có nghĩa là gì? Toàn bộ khai báo hàm có nghĩa là gì, có tính đến ý nghĩa của những thứ giữa dấu ngoặc đơn?

Biên tập

Đây không phải là một bản sao của Whats sự khác biệt của các chức năng và phương thức trong Go? : câu hỏi này đến với tôi vì tôi không biết những gì trong ngoặc đơn trước tên hàm là gì, không phải vì tôi tự hỏi sự khác biệt giữa các hàm và phương thức là gì ... nếu tôi biết rằng khai báo này là một phương thức tôi sẽ ' t đã có câu hỏi này ở nơi đầu tiên. Nếu ai đó có cùng nghi ngờ với tôi một ngày, tôi không tin cô ấy sẽ tìm kiếm "phương pháp golang" bởi vì cô ấy không biết rằng đây là trường hợp. Nó giống như tự hỏi chữ "sigma" nghĩa là gì trước một biểu thức toán học (không biết nó có nghĩa là tổng kết) và ai đó nói rằng đó là một bản sao của sự khác biệt giữa tổng và một số thứ khác.

Ngoài ra, câu trả lời ngắn cho câu hỏi này ("đó là một người nhận") không phải là câu trả lời cho "sự khác biệt giữa các chức năng và phương thức".


27
@Volker sau đó đưa ra tuyên bố từ chối trách nhiệm nói rằng những người đi trên stackoverflow chỉ trả lời những câu hỏi không có trong Tour of Go. Trong cộng đồng Haskell, mọi người có thể đặt câu hỏi như Làm cách nào tôi có thể lấy nphần tử thứ từ danh sách trong Haskell? , đó là trong phần Giới thiệu về Tìm hiểu cho bạn một Haskell cho Great Good và nhận được câu hỏi của họ mà không có sự ồn ào nào về nó.
Marcus Vinícius Monteiro

23
Khi tôi có câu hỏi này, lần đầu tiên tôi đã đi đến Tour du lịch. Tôi đã kiểm tra tất cả các tiêu đề "Chức năng" và không có ví dụ nào đề cập đến điều này. tour.golang.org/basics/4 tour.golang.org/basics/5 Nếu bạn không biết mở rộng Phương thức và giao diện, bạn sẽ không thấy tiêu đề "Phương thức là chức năng". Câu hỏi này hợp lệ và tuyệt vời cho việc lập chỉ mục của Google. Các zealots cờ trùng lặp cần phải làm sáng lên.
Bruno Bronosky

14
Cảm ơn vì đã không cụ thể trong câu hỏi của bạn, vì nó đủ để giúp tôi tìm câu trả lời!
David K

1
Bạn hỏi chính xác những gì tôi tìm kiếm, đó là một câu hỏi hợp lệ. Cảm ơn bạn. Tôi đọc tất cả các loại định nghĩa hàm và không ai giải thích điều này. Tôi vẫn cố gắng viết câu hỏi của tôi và tìm thấy điều này.
Ajak6

Câu trả lời:


199

Điều này được gọi là 'người nhận'. Trong trường hợp đầu tiên, (h handler)nó là một loại giá trị, trong trường hợp thứ hai, (s *GracefulServer)nó là một con trỏ. Cách thức hoạt động trong Go này có thể thay đổi một chút so với một số ngôn ngữ khác. Tuy nhiên, kiểu nhận, hoạt động ít nhiều giống như một lớp trong hầu hết các chương trình hướng đối tượng. Đó là thứ bạn gọi phương thức từ đó, giống như nếu tôi đặt một phương thức nào đó Abên cạnh một số lớp Personthì tôi sẽ cần một thể hiện của kiểu Personđể gọi A(giả sử đó là một phương thức cá thể và không tĩnh!).

Một Gotcha ở đây là người nhận được đẩy lên các cuộc gọi stack như lập luận khác vì vậy nếu người nhận là một loại giá trị, như trong trường hợp handlersau đó bạn sẽ được làm việc trên một bản sao trong những điều bạn gọi phương pháp này từ có nghĩa giống như h.Name = "Evan"Would không tiếp tục sau khi bạn trở lại phạm vi gọi. Vì lý do này, bất cứ điều gì mong muốn thay đổi trạng thái của người nhận, cần phải sử dụng một con trỏ hoặc trả về giá trị đã sửa đổi (cung cấp thêm mô hình loại bất biến nếu bạn đang tìm kiếm điều đó).

Đây là phần có liên quan từ thông số kỹ thuật; https://golang.org/ref/spec#Method_sets


6
Giải thích tốt và thêm điểm nghiệp để liên kết với thông số kỹ thuật có liên quan
Marius Waldal

4
Chuyến tham quan golang có một số ví dụ khá hữu ích nữa tour.golang.org/methods/1
tw_hoff

90

Nó có nghĩa ServeHTTPlà không phải là một chức năng độc lập. Dấu ngoặc đơn trước tên hàm là cách xác định đối tượng mà các hàm này sẽ hoạt động. Vì vậy, về cơ bản ServeHTTPlà một phương thức của trình xử lý kiểu và có thể được gọi bằng bất kỳ đối tượng nào, giả sử h, của trình xử lý kiểu.

h.ServeHTTP(w, r)

Họ cũng được gọi là người nhận. hai cách định nghĩa chúng. Nếu bạn muốn sửa đổi người nhận, hãy sử dụng một con trỏ như:

func (s *MyStruct) pointerMethod() { } // method on pointer

Nếu bạn không cần sửa đổi người nhận, bạn có thể định nghĩa người nhận là một giá trị như:

func (s MyStruct)  valueMethod()   { } // method on value

Ví dụ này từ sân chơi Go thể hiện khái niệm.

package main

import "fmt"

type Mutatable struct {
    a int
    b int
}

func (m Mutatable) StayTheSame() {
    m.a = 5
    m.b = 7
}

func (m *Mutatable) Mutate() {
    m.a = 5
    m.b = 7
}

func main() {
    m := &Mutatable{0, 0}
    fmt.Println(m)
    m.StayTheSame()
    fmt.Println(m)
    m.Mutate()
    fmt.Println(m)

Đầu ra của chương trình trên là:

&{0 0}
&{0 0}
&{5 7}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.