Анонимные функции и замыкания

Функция без имени, определённая прямо в выражении:

double := func(x int) int {
    return x * 2
}
fmt.Println(double(5))   // 10

Можно вызвать немедленно (IIFE):

result := func(x, y int) int {
    return x + y
}(3, 4)
fmt.Println(result)   // 7

Анонимная функция «захватывает» переменные из окружающей области видимости:

func counter() func() int {
    n := 0
    return func() int {
        n++
        return n
    }
}

c := counter()
fmt.Println(c())   // 1
fmt.Println(c())   // 2
fmt.Println(c())   // 3

n живёт, пока жива функция c — сборщик мусора не удалит её раньше.

Классическая ошибка: все замыкания захватывают одну и ту же переменную i:

funcs := make([]func(), 3)
for i := 0; i < 3; i++ {
    i := i   // новая переменная на каждой итерации
    funcs[i] = func() { fmt.Println(i) }
}
for _, f := range funcs {
    f()  // 0, 1, 2
}

Без повторного i := i все три функции напечатали бы 3.

// Мидлвар / декоратор
func withLogging(f func(int) int) func(int) int {
    return func(x int) int {
        fmt.Printf("вызов с %d\n", x)
        return f(x)
    }
}

ЗаданиеСложность
1Упражнение 1easy
2Упражнение 2medium
3Упражнение 3hard