Счётчик как значение-функция
Сохраните программу в main.go и запустите командой go run main.go.
package main
import "fmt"
type transform func(int) int
func apply(values []int, transform transform) []int {
result := make([]int, 0, len(values))
for _, value := range values {
result = append(result, transform(value))
}
return result
}
func makeMultiplier(factor int) transform {
return func(value int) int {
return value * factor
}
}
func main() {
values := []int{2, 4, 6}
triple := makeMultiplier(3)
fmt.Println(apply(values, triple))
threshold := 5
countAbove := 0
visit := func(value int) {
if value > threshold {
countAbove++
}
}
for _, value := range values {
visit(value)
}
fmt.Println("больше порога:", countAbove)
}
В первом результате функция, созданная внутри makeMultiplier, умножает каждое число на сохранённый множитель. Во втором замыкание читает threshold и изменяет countAbove, объявленные во внешней функции.
Функция внутри выражения
Функциональный литерал — это объявление функции без имени, записанное как значение: func(value int) int { ... }. Его можно присвоить переменной, сразу вызвать или передать аргументом. Функции удобно передавать как callback, когда вызывающий код управляет перебором, а пользователь задаёт действие для каждого элемента.
В примере определён именованный тип функции transform. Он делает сигнатуру параметра apply короче и даёт понятное имя роли. Обычный именованный тип и псевдоним типа — разные конструкции: type transform func(int) int создаёт отдельное имя типа, а type transform = func(int) int объявляет alias.
Замыкание и захваченные переменные
Литерал может обращаться к переменным внешней области видимости. Такая функция вместе с доступом к этим переменным называется замыканием. makeMultiplier возвращает функцию, а параметр factor продолжает быть доступным после завершения вызова makeMultiplier: замыкание сохраняет окружение, необходимое для дальнейшей работы.
Замыкание захватывает переменную, а не снимок её значения в момент объявления. Если внешнее значение позже изменить, вызов замыкания увидит новое значение. Если нужна независимая копия, передайте значение параметром или сохраните его в отдельной переменной.
Состояние в замыкании удобно для счётчиков и небольшого контекста операции. Следите за тем, кто меняет захваченные переменные: несколько вызовов могут разделять одно и то же состояние. При одновременном доступе обычная переменная требует синхронизации так же, как и поле структуры.