Lecciones del módulo (4/5)
Clausuras y funciones como valores
En Go, las funciones son valores de primera clase: se pueden asignar a variables, pasadas a otras funciones y devueltas. Un cierre es un función literal (anónima) que captura las variables del entorno en el que se define.
Función literal
Una función sin nombre, escrita en línea. Lo llamas inmediatamente o asignarlo:
greet := func(name string) {
fmt.Println("ciao", name)
}
greet("Anna")
// invocata immediatamente:
func() { fmt.Println("subito") }()El tipo de greet es func(string).
Capturando el entorno: cierre
La función literal puede leer y modificar las variables visibles en su alcance léxico, incluso después de que la función externa haya regresado:
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
fmt.Println(c(), c(), c()) // 1 2 3n "vive" siempre que al menos un cierre haga referencia a él. Cada llamada a
counter() crea un n nuevo e independiente.
Cierre como devolución de llamada
Un patrón muy común:
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})El cierre captura nums y define el orden.
Funciones como parámetros
Para aceptar una función como parámetro, escriba su tipo:
func apply(nums []int, f func(int) int) []int {
out := make([]int, len(nums))
for i, n := range nums {
out[i] = f(n)
}
return out
}
double := func(x int) int { return x * 2 }
apply([]int{1, 2, 3}, double) // [2 4 6]Si la firma resulta difícil de leer, defina un tipo alias:
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }Pruébalo
Defina contador() que devuelva un cierre: cada llamada al cierre se incrementa y devuelve un contador interno.
Mostrar pista
`n` debe declararse ANTES de la devolución; el cierre lo captura.
Solución disponible después de 3 intentos
Asigne a f una función literal que imprima 'ciao' y luego llámela.
Mostrar pista
Sintaxis: `f := func() { ... }` y luego `f()`.
Solución disponible después de 3 intentos
¿Qué imprime esto? (cuidado con el alcance del cierre)
mk := func() func() int {
x := 0
return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())Resumen
- Las funciones son de primera clase: asignables, transitables, retornables.
- Función literal:
func(params) ret { ... }, anónima. - Cierre: captura las variables del alcance léxico, las mantiene vivas.
- Tipo de función explícita en parámetros:
func(int) int. - Desde Go 1.22, cada iteración for tiene su propia copia de la variable de bucle.