Круглые скобки в конце анонимной функции
Подскажите пожалуйста зачем нужны круглые скобки, которые за фигурными, в самом конце кода? Я знаю, что эти скобки значат вызов на месте, но я все равно потом вызываю этот кусок кода через fn().
Дайте пожалуйста ответ более развернуто. 5-ый час не могу въехать почему.
fn := func() func(int) int {
count := 0
return func(i int) int {
count++
return count * i
}
}()
Ответы (1 шт):
Ваша анонимная функция, которую вы вызываете пустыми скобками в конце вашего кода, возвращает другую функцию, которая присваивается переменной 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