Круглые скобки в конце анонимной функции

Рейтинг: 0Ответов: 1Опубликовано: 07.02.2023

Подскажите пожалуйста зачем нужны круглые скобки, которые за фигурными, в самом конце кода? Я знаю, что эти скобки значат вызов на месте, но я все равно потом вызываю этот кусок кода через fn().

Дайте пожалуйста ответ более развернуто. 5-ый час не могу въехать почему.

fn := func() func(int) int {
        count := 0
        return func(i int) int {
            count++
            return count * i
        }
    }()

Ответы

▲ 2Принят

Ваша анонимная функция, которую вы вызываете пустыми скобками в конце вашего кода, возвращает другую функцию, которая присваивается переменной 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