Modulelessen (4/5)
Afsluitingen en functies als waarden
In Go zijn functies eersteklaswaarden: ze kunnen worden toegewezen variabelen, doorgegeven aan andere functies en geretourneerd. Een sluiting is een functie letterlijk (anoniem) die de variabelen vastlegt van de omgeving waarin het wordt gedefinieerd.
Functie letterlijk
Een functie zonder naam, inline geschreven. Je noemt het meteen of wijs het toe:
greet := func(name string) {
fmt.Println("ciao", name)
}
greet("Anna")
// invocata immediatamente:
func() { fmt.Println("subito") }()Het type greet is func(string).
Het vastleggen van de omgeving: afsluiting
De functie letterlijk kan de zichtbare variabelen lezen en wijzigen zijn lexicale reikwijdte, zelfs nadat de uiterlijke functie is teruggekeerd:
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
fmt.Println(c(), c(), c()) // 1 2 3n "leeft" zolang minstens één afsluiting ernaar verwijst. Elke oproep naar
counter() creëert een nieuwe, onafhankelijke n.
Sluiting als terugbelverzoek
Een veel voorkomend patroon:
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})De afsluiting legt nums vast en definieert de volgorde.
Functioneert als parameters
Om een functie als parameter te accepteren, schrijft u het type ervan op:
func apply(nums []int, f func(int) int) []int {
out := make([]int, len(nums))
for i, n := range nums {
out[i] = f(n)
}
return out
}
double := func(x int) int { return x * 2 }
apply([]int{1, 2, 3}, double) // [2 4 6]Als de handtekening moeilijk leesbaar wordt, definieer dan een typealias:
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }Probeer het
Definieer counter() die een afsluiting retourneert: elke aanroep naar de afsluiting wordt verhoogd en retourneert een interne teller.
Toon hint
`n` moet VOOR de terugkeer worden aangegeven; de sluiting vangt het op.
Oplossing beschikbaar na 3 pogingen
Wijs aan f een letterlijke functie toe die 'ciao' afdrukt, en roep deze vervolgens aan.
Toon hint
Syntaxis: `f := func() { ... }` en vervolgens `f()`.
Oplossing beschikbaar na 3 pogingen
Wat drukt dit af? (let op sluitingsbereik)
mk := func() func() int {
x := 0
return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())Samenvatten
- Functies zijn eersteklas: toewijsbaar, redelijk, herbruikbaar.
- Functie letterlijk:
func(params) ret { ... }, anoniem. - Sluiting: vangt de variabelen van de lexicale reikwijdte op en houdt ze levend.
- Expliciet functietype in parameters:
func(int) int. - Sinds Go 1.22 heeft elke for-iteratie zijn eigen kopie van de lusvariabele.