Saltar al contenido principal
eLearner.app
Módulo 3 · Lección 4 de 514/50 en el curso~12 min
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:

Go
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:

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

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

n "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:

Go
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:

Go
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:

Go
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }

Pruébalo

Ejercicio#go.m3.l4.e1
Intentos: 0Cargando...

Defina contador() que devuelva un cierre: cada llamada al cierre se incrementa y devuelve un contador interno.

Cargando editor...
Mostrar pista

`n` debe declararse ANTES de la devolución; el cierre lo captura.

Solución disponible después de 3 intentos

Ejercicio#go.m3.l4.e2
Intentos: 0Cargando...

Asigne a f una función literal que imprima 'ciao' y luego llámela.

Cargando editor...
Mostrar pista

Sintaxis: `f := func() { ... }` y luego `f()`.

Solución disponible después de 3 intentos

Cuestionario#go.m3.l4.e3
Listo

¿Qué imprime esto? (cuidado con el alcance del cierre)

Go
mk := func() func() int {
    x := 0
    return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())
Opciones de respuesta

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.