Go
nedläggningar
Sök…
Grunderna för stängning
En stängning är en funktion som tas tillsammans med en miljö. Funktionen är vanligtvis en anonym funktion definierad i en annan funktion. Miljön är den lexiska räckvidden för den inneslutna funktionen (mycket grundläggande idé om en lexikalisk räckvidd för en funktion skulle vara omfattningen som finns mellan funktionens hängslen.)
func g() {
i := 0
f := func() { // anonymous function
fmt.Println("f called")
}
}
Inom kroppen av en anonym funktion (säg f
) definierad inom en annan funktion (säg g
), är variabler som finns i räckvidden för både f
och g
tillgängliga. Det är emellertid omfattningen av g
som utgör miljön som en del av stängningen (funktionsdel är f
) och som ett resultat behåller ändringar som gjorts i variablerna i g
: s räckvidd sina värden (dvs. miljön kvarstår mellan samtal till f
) .
Tänk på funktionen nedan:
func NaturalNumbers() func() int {
i := 0
f:= func() int { // f is the function part of closure
i++
return i
}
return f
}
I ovanstående definition har NaturalNumbers
en inre funktion f
som NaturalNumbers
returnerar. Inuti f
åtkomst till variabel i
definierad inom ramen för NaturalNumbers
.
Vi får en ny funktion från NaturalNumbers
så:
n := NaturalNumbers()
Nu är n
en stängning. Det är en funktion (definierad av f
) som också har en tillhörande miljö (omfattning av NaturalNumbers
).
I fallet med n
innehåller miljödelen bara en variabel: i
Eftersom n
är en funktion kan den kallas:
fmt.Println(n()) // 1
fmt.Println(n()) // 2
fmt.Println(n()) // 3
Såsom framgår av ovanstående utgång, varje gång n
kallas, ökar det i
. i
börjar vid 0, och varje samtal till n
kör i++
.
Värdet på i
behålls mellan samtal. Det vill säga, miljön, som en del av stängningen, kvarstår.
Att ringa NaturalNumbers
igen skulle skapa och returnera en ny funktion. Detta skulle initiera ett nytt i
inom NaturalNumbers
. Vilket innebär att den nyligen återvunna funktionen bildar en annan stängning som har samma del för funktion (fortfarande f
) men en helt ny miljö (en nyinitialiserad i
).
o := NaturalNumbers()
fmt.Println(n()) // 4
fmt.Println(o()) // 1
fmt.Println(o()) // 2
fmt.Println(n()) // 5
Både n
och o
är stängningar som innehåller samma funktionsdel (vilket ger dem samma beteende), men olika miljöer. Således möjliggör användning av stängningar att funktioner har tillgång till en bestående miljö som kan användas för att behålla information mellan samtal.
Ett annat exempel:
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