Go
Verschlüsse
Suche…
Schließungsgrundlagen
Ein Abschluss ist eine Funktion, die zusammen mit einer Umgebung genommen wird. Die Funktion ist normalerweise eine anonyme Funktion, die in einer anderen Funktion definiert ist. Die Umgebung ist der lexikalische Geltungsbereich der einschließenden Funktion (eine grundlegende Idee eines lexikalischen Gültigkeitsbereichs einer Funktion wäre der Gültigkeitsbereich, der zwischen den geschweiften Klammern der Funktion besteht.)
func g() {
i := 0
f := func() { // anonymous function
fmt.Println("f called")
}
}
Innerhalb des Körpers einer anonymen Funktion (etwa f
), die in einer anderen Funktion (beispielsweise g
) definiert ist, sind Variablen zugänglich, die in Bereichen von sowohl f
als auch g
sind. Es ist jedoch der Bereich von g
, der den Umgebungsteil der Schließung bildet (Funktionsteil ist f
). Als Folge davon behalten Änderungen an den Variablen im Bereich von g
ihre Werte bei (dh die Umgebung bleibt zwischen Aufrufen von f
) .
Betrachten Sie die folgende Funktion:
func NaturalNumbers() func() int {
i := 0
f:= func() int { // f is the function part of closure
i++
return i
}
return f
}
In der obigen Definition hat NaturalNumbers
eine innere Funktion f
die NaturalNumbers
zurückgibt. Innerhalb von f
wird auf die im Rahmen von NaturalNumbers
definierte Variable i
zugegriffen.
Wir bekommen eine neue Funktion von NaturalNumbers
wie NaturalNumbers
:
n := NaturalNumbers()
Nun ist n
eine Schließung. Es ist eine Funktion (definiert durch f
), der auch eine zugehörige Umgebung (Umfang von NaturalNumbers
) zugeordnet ist.
Im Fall von n
enthält der Umgebungsabschnitt nur eine Variable: i
Da n
eine Funktion ist, kann es aufgerufen werden:
fmt.Println(n()) // 1
fmt.Println(n()) // 2
fmt.Println(n()) // 3
Wie aus der obigen Ausgabe hervorgeht, erhöht sich jedes Mal, wenn n
aufgerufen wird, i
. i
beginnt bei 0 und jeder Aufruf an n
führt i++
.
Der Wert von i
wird zwischen Aufrufen beibehalten. Das heißt, die Umwelt als Teil der Schließung bleibt bestehen.
NaturalNumbers
Sie NaturalNumbers
erneut NaturalNumbers
, wird eine neue Funktion erstellt und zurückgegeben. Dies würde ein neues i
in NaturalNumbers
initialisieren. Das bedeutet, dass die neu zurückgegebene Funktion einen weiteren Abschluss bildet, der den gleichen Teil für die Funktion (noch f
) aufweist, aber eine völlig neue Umgebung (ein neu initialisiertes i
).
o := NaturalNumbers()
fmt.Println(n()) // 4
fmt.Println(o()) // 1
fmt.Println(o()) // 2
fmt.Println(n()) // 5
Sowohl n
als auch o
sind Verschlüsse, die denselben Funktionsteil enthalten (was dasselbe Verhalten bewirkt), aber unterschiedliche Umgebungen. Durch die Verwendung von Verschlüssen können Funktionen auf eine permanente Umgebung zugreifen, in der Informationen zwischen Aufrufen gespeichert werden können.
Ein anderes Beispiel:
func multiples(i int) func() int {
var x int = 0
return func() int {
x++
// paramenter to multiples (here it is i) also forms
// a part of the environment, and is retained
return x * i
}
}
two := multiples(2)
fmt.Println(two(), two(), two()) // 2 4 6
fortyTwo := multiples(42)
fmt.Println(fortyTwo(), fortyTwo(), fortyTwo()) // 42 84 126