Ваша анонимная функция, которую вы вызываете пустыми скобками в конце вашего кода, возвращает другую функцию, которая присваивается переменной fn
.
Вызов анонимной функции при её объявлении эквивалентен присвоению её в переменную и вызову из этой переменной.
Рассмотрим пример на основе вашего кода. Здесь мы присваиваем эту анонимную функцию переменной makeFn
(обратите внимание, без круглых скобок после фигурных). Затем вызываем эту функцию, и результат присваиваем переменной fn
(прямо как в вашем коде). Затем вызываем уже функцию fn
, и результат записываем в переменную r
. Для наглядности выведем типы этих переменных. Как видите, makeFn
имеет тип функции, возвращающей функцию, fn
имеет тип функции возвращающей целое число, а r
имеет тип целого числа.
package main
import "fmt"
func main() {
makeFn := func() func(int) int {
count := 0
return func(i int) int {
count++
return count * i
}
}
fn := makeFn()
r := fn(2)
fmt.Printf("typeof(makeFn): %T\n", makeFn)
fmt.Printf("typeof(fn): %T\n", fn)
fmt.Printf("typeof(r): %T\n", r)
}
Вывод:
typeof(makeFn): func() func(int) int
typeof(fn): func(int) int
typeof(r): int
Может возникнуть вопрос: зачем нам нужна промежуточная функция (makeFn
), если можно сразу записать нужную функцию в переменную fn
? Конкретно в данном случае это необходимо для замыкания (closure). Переменная count
оказывается в замыкании, и если мы вдруг захотим создать несколько экземпляров функции fn
, то у каждого экземпляра будет своя независимая переменная count
. Пример:
package main
import "fmt"
func main() {
makeFn := func() func(int) int {
count := 0
return func(i int) int {
count++
return count * i
}
}
fn1, fn2 := makeFn(), makeFn()
fmt.Printf("fn1: ")
for i := 1; i <= 3; i++ {
fmt.Printf("%d ", fn1(i))
}
fmt.Println()
fmt.Printf("fn2: ")
for i := -1; i >= -3; i-- {
fmt.Printf("%d ", fn2(i))
}
fmt.Println()
}
Вывод:
fn1: 1 4 9
fn2: -1 -4 -9