Składnia deklaracji funkcji: rzeczy w nawiasach przed nazwą funkcji

249

Przepraszam, że nie mogłem sprecyzować tytułu pytania, ale czytałem trochę kodu Go i napotkałem deklaracje funkcji tego formularza:

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

z https://github.com/mattermost/platform/blob/master/api/context.go

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

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

Co oznacza nawias (h handler)i (s *GracefulServer)pomiędzy nimi? Co oznacza cała deklaracja funkcji, biorąc pod uwagę znaczenie rzeczy między nawiasami?

Edytować

To nie jest duplikat Jaka jest różnica funkcji i metod w Go? : to pytanie przyszło mi do głowy, ponieważ nie wiedziałem, co to są w nawiasach przed nazwą funkcji, a nie dlatego, że zastanawiałem się, jaka jest różnica między funkcjami i metodami ... gdybym wiedział, że ta deklaracja jest metodą, której nie zrobiłbym po pierwsze miałem to pytanie. Jeśli pewnego dnia ktoś ma takie same wątpliwości jak ja, nie sądzę, by poszła szukać „metod golang”, ponieważ nie wie, że tak jest. To tak, jakby zastanawiać się, co oznacza litera „sigma” przed wyrażeniem matematycznym (nie wiedzieć, że oznacza to sumowanie), a ktoś mówi, że jest duplikatem różnicy między sumowaniem a czymś innym.

Krótka odpowiedź na to pytanie („to odbiornik”) nie jest odpowiedzią na „jaka jest różnica między funkcjami a metodami”.

Marcus Vinícius Monteiro
źródło
27
@Volker umieścił zrzeczenie się odpowiedzialności, mówiąc, że ludzie Go na stackoverflow odpowiadają tylko na pytania, które nie są w Tour of Go. W społeczności Haskell ludzie mogą zadawać pytania typu Jak mogę uzyskać nelement z listy w Haskell? , który znajduje się we wstępie „ Naucz się Haskella dla wielkiego dobra” i uzyskaj odpowiedź na ich pytania bez kłopotów z tym związanych.
Marcus Vinícius Monteiro,
23
Kiedy miałem to pytanie, po raz pierwszy pojechałem na Go Tour. Sprawdziłem wszystkie tytuły „Funkcja” i żaden z przykładów tego nie obejmował. tour.golang.org/basics/4 tour.golang.org/basics/5 Jeśli nie wiesz, jak rozwinąć Metody i interfejsy, nie zobaczysz tytułu „Metody to funkcje”. To pytanie jest ważne i doskonałe do indeksowania Google. Zduplikowani fanatycy flagi muszą się rozjaśnić.
Bruno Bronosky,
14
Dziękuję, że nie sprecyzowałem twojego pytania, ponieważ to wystarczyło, aby pomóc mi znaleźć odpowiedź!
David K
1
Zadałeś dokładnie to, czego szukałem, to prawidłowe pytanie. Dziękuję Ci. Czytam wszelkiego rodzaju definicje funkcji i nikt tego nie wyjaśnił. Wciąż próbowałem napisać moje pytanie dotyczące nube i znalazłem to.
Ajak6

Odpowiedzi:

200

Nazywa się to „odbiornikiem”. W pierwszym przypadku (h handler)jest to typ wartości, w drugim (s *GracefulServer)wskaźnik. Sposób działania w Go może się nieco różnić w zależności od niektórych innych języków. Jednak typ odbierający działa mniej więcej jak klasa w większości programowania obiektowego. Jest to rzecz, z której wywołujesz metodę, podobnie jak gdybym umieścił jakąś metodę Ana boku jakiejś klasy, Personwtedy potrzebowałbym instancji typu Personw celu wywołania A(zakładając, że jest to metoda instancji, a nie statyczna!).

Jeden haczyka tutaj jest to, że odbiornik zostaje umieszczana na stosie połączeń, podobnie jak inne argumenty, więc jeśli odbiornik jest typ wartości, podobnie jak w przypadku handlerwtedy będzie pracować na kopii rzeczą, którą nazywa się metodą z oznacza coś h.Name = "Evan"BĘDZIE nie utrzymują się po powrocie do zakresu wywoływania. Z tego powodu wszystko, co oczekuje zmiany stanu odbiornika, musi użyć wskaźnika lub zwrócić zmodyfikowaną wartość (daje więcej niezmiennego paradygmatu typu, jeśli tego szukasz).

Oto odpowiednia sekcja ze specyfikacji; https://golang.org/ref/spec#Method_sets

evanmcdonnal
źródło
6
Dobre wyjaśnienie i dodatkowe punkty karmy za linkowanie do odpowiedniej specyfikacji
Marius Waldal,
4
Trasa do Golang ma też kilka użytecznych przykładów tour.golang.org/methods/1
tw_hoff
90

Oznacza ServeHTTPto, że nie jest samodzielną funkcją. Nawias przed nazwą funkcji to Go metoda definiowania obiektu, na którym te funkcje będą działać. Zasadniczo ServeHTTPjest to metoda obsługi typów i można ją wywoływać za pomocą dowolnego obiektu, powiedzmy h, z procedury obsługi typów.

h.ServeHTTP(w, r)

Są również nazywane odbiornikami. Istnieją dwa sposoby ich zdefiniowania. Jeśli chcesz zmodyfikować odbiornik, użyj wskaźnika takiego jak:

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

Jeśli nie musisz modyfikować odbiornika, możesz zdefiniować odbiornik jako wartość:

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

Ten przykład z placu zabaw Go demonstruje tę koncepcję.

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)

Dane wyjściowe powyższego programu to:

&{0 0}
&{0 0}
&{5 7}
Abhishek Nalin
źródło