Syntax der Funktionsdeklaration: Dinge in Klammern vor dem Funktionsnamen

248

Es tut mir leid, dass ich im Titel der Frage nicht genauer sein konnte, aber ich habe einen Go- Code gelesen und bin auf Funktionsdeklarationen dieser Form gestoßen:

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

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

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

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

Was bedeutet das (h handler)und das (s *GracefulServer)zwischen Klammern? Was bedeutet die gesamte Funktionsdeklaration unter Berücksichtigung der Bedeutung der Dinge in Klammern?

Bearbeiten

Dies ist kein Duplikat von Was ist der Unterschied zwischen Funktionen und Methoden in Go? : Diese Frage kam zu mir, weil ich nicht wusste, was die Dinge in Klammern vor dem Funktionsnamen waren, nicht weil ich mich fragte, was der Unterschied zwischen Funktionen und Methoden war ... wenn ich wüsste, dass diese Deklaration eine Methode ist, würde ich nicht ' Ich hatte diese Frage überhaupt nicht. Wenn jemand eines Tages den gleichen Zweifel wie ich hat, glaube ich nicht, dass sie nach "Golang-Methoden" suchen wird, weil sie nicht weiß, dass dies der Fall ist. Es wäre, als würde man sich fragen, was der Buchstabe "Sigma" vor einem mathematischen Ausdruck bedeutet (ohne zu wissen, dass er Summation bedeutet), und jemand sagt, es sei ein Duplikat dessen, was den Unterschied zwischen Summation und etwas anderem ausmacht.

Die kurze Antwort auf diese Frage ("es ist ein Empfänger") ist auch keine Antwort auf "Was ist der Unterschied zwischen Funktionen und Methoden?".

Marcus Vinícius Monteiro
quelle
27
@Volker hat dann einen Haftungsausschluss eingefügt, der besagt, dass die Go-Leute im Stackoverflow nur Fragen beantworten, die nicht auf der Tour of Go sind. In der Haskell-Community können Leute Fragen stellen wie Wie kann ich das nElement aus der Liste in Haskell entfernen? , das in der Einführung zu Learn you a Haskell for Great Good steht und deren Fragen ohne viel Aufhebens beantwortet werden.
Marcus Vinícius Monteiro
23
Als ich diese Frage hatte, ging ich zuerst zur Go Tour. Ich habe alle "Funktion" -Titel überprüft und keines der Beispiele hat dies behandelt. tour.golang.org/basics/4 tour.golang.org/basics/5 Wenn Sie Methoden und Schnittstellen nicht erweitern können, wird der Titel "Methoden sind Funktionen" nicht angezeigt . Diese Frage ist gültig und ideal für die Google-Indizierung. Die doppelten Flaggen-Eiferer müssen aufhellen.
Bruno Bronosky
14
Vielen Dank, dass Sie in Ihrer Frage nicht spezifisch sind, denn es hat mir geholfen, die Antwort zu finden!
David K.
1
Sie haben genau gefragt, wonach ich gesucht habe, es ist eine gültige Frage. Danke dir. Ich habe alle Arten von Funktionsdefinitionen gelesen und niemand hat dies erklärt. Ich habe immer noch versucht, meine Nube-Frage zu schreiben und habe diese gefunden.
Ajak6

Antworten:

199

Dies wird als "Empfänger" bezeichnet. Im ersten Fall handelt (h handler)es sich um einen Werttyp, im zweiten(s *GracefulServer) um einen Zeiger. Die Funktionsweise in Go kann sich geringfügig von einigen anderen Sprachen unterscheiden. Der empfangende Typ funktioniert jedoch in den meisten objektorientierten Programmen mehr oder weniger wie eine Klasse. Es ist die Sache, von der aus Sie die Methode aufrufen, ähnlich wie wenn ich eine Methode Aneben eine Klasse stelle, Persondann würde ich eine Instanz vom Typ benötigen, Personum sie aufzurufen A(vorausgesetzt, es ist eine Instanzmethode und keine statische!).

Ein Problem hierbei ist, dass der Empfänger wie andere Argumente auf den Aufrufstapel geschoben wird. Wenn der Empfänger also ein Werttyp ist, wie im Fall von handler, arbeiten Sie an einer Kopie des Dings, das Sie als Methode bezeichnet haben, aus einer Bedeutung wie " h.Name = "Evan"würde" nicht bestehen bleiben, nachdem Sie zum aufrufenden Bereich zurückgekehrt sind. Aus diesem Grund muss alles, was erwartet, den Status des Empfängers zu ändern, einen Zeiger verwenden oder den geänderten Wert zurückgeben (gibt eher ein unveränderliches Typ-Paradigma, wenn Sie danach suchen).

Hier ist der relevante Abschnitt aus der Spezifikation; https://golang.org/ref/spec#Method_sets

evanmcdonnal
quelle
6
Gute Erklärung und zusätzliche Karma-Punkte für die Verknüpfung mit der relevanten Spezifikation
Marius Waldal
4
Die Golang-Tour hat auch einige ziemlich nützliche Beispiele tour.golang.org/methods/1
tw_hoff
90

Dies bedeutet, dass ServeHTTPes sich nicht um eine eigenständige Funktion handelt. Die Klammer vor dem Funktionsnamen ist die Go-Methode zum Definieren des Objekts, mit dem diese Funktionen ausgeführt werden. Es handelt sich also im Wesentlichen ServeHTTPum eine Methode des Typhandlers, die mit einem beliebigen Objekt, z. B. h, des Typhandlers aufgerufen werden kann.

h.ServeHTTP(w, r)

Sie werden auch Empfänger genannt. Es gibt zwei Möglichkeiten, sie zu definieren. Wenn Sie den Empfänger ändern möchten, verwenden Sie einen Zeiger wie:

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

Wenn Sie den Empfänger nicht ändern müssen, können Sie den Empfänger wie folgt definieren:

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

Dieses Beispiel vom Go-Spielplatz zeigt das Konzept.

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)

Die Ausgabe des obigen Programms ist:

&{0 0}
&{0 0}
&{5 7}
Abhishek Nalin
quelle