Lektionen des Moduls (4/5)
Closures und Funktionen als Werte
In Go sind Funktionen erstklassige Werte: Sie können ihnen zugewiesen werden Variablen, die an andere Funktionen übergeben und zurückgegeben werden. Ein Abschluss ist ein Funktionsliteral (anonym), das die Variablen des erfasst Umgebung, in der es definiert ist.
Funktionsliteral
Eine Funktion ohne Namen, inline geschrieben. Du rufst es sofort an bzw weisen Sie es zu:
greet := func(name string) {
fmt.Println("ciao", name)
}
greet("Anna")
// invocata immediatamente:
func() { fmt.Println("subito") }()Der Typ von greet ist func(string).
Die Umgebung erfassen: Schließung
Das Funktionsliteral kann die in sichtbaren Variablen lesen und ändern sein lexikalischer Geltungsbereich, auch nachdem die äußere Funktion zurückgegeben wurde:
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
fmt.Println(c(), c(), c()) // 1 2 3n „lebt“, solange mindestens ein Abschluss darauf verweist. Jeder Anruf an
counter() erstellt einen neuen, unabhängigen n.
Abschluss als Rückruf
Ein sehr häufiges Muster:
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})Der Abschluss erfasst nums und definiert die Reihenfolge.
Fungiert als Parameter
Um eine Funktion als Parameter zu akzeptieren, schreiben Sie ihren Typ aus:
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]Wenn die Signatur schwer lesbar wird, definieren Sie einen Typalias:
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }Probieren Sie es aus
Definieren Sie counter(), das einen Abschluss zurückgibt: Jeder Aufruf des Abschlusses erhöht und gibt einen internen Zähler zurück.
Hinweis anzeigen
`n` muss VOR der Rückgabe deklariert werden; der Verschluss fängt es ein.
Lösung nach 3 Versuchen verfügbar
Weisen Sie f ein Funktionsliteral zu, das „ciao“ ausgibt, und rufen Sie es dann auf.
Hinweis anzeigen
Syntax: `f := func() { ... }`, dann `f()`.
Lösung nach 3 Versuchen verfügbar
Was wird hier gedruckt? (Achten Sie auf den Schließungsbereich)
mk := func() func() int {
x := 0
return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())Zusammenfassung
- Funktionen sind erstklassig: zuweisbar, passierbar, rückzahlbar.
- Funktionsliteral:
func(params) ret { ... }, anonym. - Abschluss: Erfasst die Variablen des lexikalischen Bereichs und hält sie am Leben.
- Expliziter Funktionstyp in Parametern:
func(int) int. - Seit Go 1.22 hat jede for-Iteration eine eigene Kopie der Schleifenvariablen.