lo para Go: guía completa con ejemplos prácticos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Librería lo para Go: Utilidades Genéricas (Lodash para Go)

En el desarrollo con Go, a menudo surge la necesidad de funciones prácticas para trabajar con colecciones, similares a las que existen en otros lenguajes (como map, filter, reduce de JavaScript o Python). La biblioteca estándar de Go ofrece un conjunto mínimo de herramientas, y escribir bucles for repetitivos para cada operación se vuelve tedioso. Aquí es donde entra en juego la librería lo: un potente conjunto de utilidades genéricas, inspirado en la popular librería JavaScript Lodash.

La librería lo utiliza genéricos (tipos genéricos), disponibles desde Go 1.18+, para proporcionar funciones tiposeguras para trabajar con slices, maps, canales y otras estructuras de datos. En lugar de escribir for i := range slice { ... } para cada transformación, puedes usar una sola línea de código: lo.Map(slice, transformFunc). Esto hace que el código sea más legible, conciso y menos propenso a errores.

¿Por qué usar lo? Primero, ahorra tiempo: dejas de escribir código boilerplate. Segundo, aumenta la fiabilidad: las funciones de la librería están minuciosamente probadas y cubren muchos casos extremos. Tercero, aporta uniformidad: todo el equipo usa las mismas funciones con nombres claros, lo que simplifica las revisiones de código. lo es una herramienta imprescindible para cualquier proyecto Go que maneje colecciones de datos de forma intensiva.

Instalación

La instalación de la librería lo se realiza de la forma estándar en Go mediante go get. Asegúrate de tener instalada la versión Go 1.18 o superior (ya que la librería usa genéricos).

go get github.com/samber/lo@latest

Después de ejecutar este comando, la librería se añadirá a tu archivo go.mod. Ahora puedes importarla en tu código:

import "github.com/samber/lo"

Inicio rápido

Escribamos un programa sencillo que use lo para filtrar y transformar un slice de números.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    // Slice original de números
    numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    // Filtramos solo los números pares
    evenNumbers := lo.Filter(numbers, func(x int, _ int) bool {
        return x%2 == 0
    })
    fmt.Println("Números pares:", evenNumbers) // [2 4 6 8 10]

    // Duplicamos cada número
    doubled := lo.Map(evenNumbers, func(x int, _ int) int {
        return x * 2
    })
    fmt.Println("Pares duplicados:", doubled) // [4 8 12 16 20]

    // Sumamos todos los números
    sum := lo.Sum(doubled)
    fmt.Println("Suma:", sum) // 60
}

Como ves, el código es mucho más declarativo y legible. Hemos evitado escribir tres bucles for separados.

Métodos y funciones principales

A continuación, se muestra una lista de las funciones clave de la librería lo con ejemplos de uso. La mayoría de las funciones aceptan un slice y una función de callback.

1. lo.Filter

Firma: func Filter[T any](collection []T, predicate func(item T, index int) bool) []T

Qué hace: Crea un nuevo slice que contiene solo los elementos del slice original para los cuales la función predicado devuelve true.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    names := []string{"Ana", "Luis", "Carlos", "David", "Eva"}
    // Dejamos solo los nombres con más de 3 caracteres
    longNames := lo.Filter(names, func(name string, _ int) bool {
        return len(name) > 3
    })
    fmt.Println(longNames) // [Carlos David]
}

2. lo.Map

Firma: func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R

Qué hace: Transforma cada elemento de un slice aplicando una función, y devuelve un nuevo slice con los resultados.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    // Elevamos al cuadrado cada número
    squares := lo.Map(numbers, func(x int, _ int) int {
        return x * x
    })
    fmt.Println(squares) // [1 4 9 16 25]
}

3. lo.Reduce

Firma: func Reduce[T any, R any](collection []T, accumulator func(agg R, item T, index int) R, initial R) R

Qué hace: Reduce un slice a un único valor aplicando una función acumuladora de izquierda a derecha, comenzando con un valor inicial.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    // Calculamos el producto de todos los números
    product := lo.Reduce(numbers, func(agg int, item int, _ int) int {
        return agg * item
    }, 1)
    fmt.Println(product) // 120
}

4. lo.Find

Firma: func Find[T any](collection []T, predicate func(item T) bool) (T, bool)

Qué hace: Busca el primer elemento en un slice que cumple la condición dada. Devuelve el elemento y un booleano indicando si se encontró.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    ages := []int{15, 22, 18, 30, 12}
    // Buscamos el primer mayor de edad (edad >= 18)
    adult, found := lo.Find(ages, func(age int) bool {
        return age >= 18
    })
    if found {
        fmt.Println("Primer adulto encontrado:", adult) // 22
    }
}

5. lo.Uniq

Firma: func Uniq[T comparable](collection []T) []T

Qué hace: Elimina elementos duplicados de un slice, manteniendo el orden de la primera aparición.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    items := []string{"manzana", "pera", "manzana", "uva", "pera"}
    uniqueItems := lo.Uniq(items)
    fmt.Println(uniqueItems) // [manzana pera uva]
}

6. lo.Chunk

Firma: func Chunk[T any](collection []T, size int) [][]T

Qué hace: Divide un slice en sub-slices (fragmentos) del tamaño especificado. Útil para procesamiento por lotes.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5, 6, 7}
    chunks := lo.Chunk(numbers, 3)
    fmt.Println(chunks) // [[1 2 3] [4 5 6] [7]]
}

7. lo.Flatten

Firma: func Flatten[T any](collection [][]T) []T

Qué hace: Aplana un slice de slices en un solo slice (una sola dimensión).

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    matrix := [][]int{{1, 2}, {3, 4}, {5, 6}}
    flat := lo.Flatten(matrix)
    fmt.Println(flat) // [1 2 3 4 5 6]
}

8. lo.Sum

Firma: func Sum[T constraints.Integer | constraints.Float](collection []T) T

Qué hace: Calcula la suma de todos los elementos numéricos de un slice.

package main

import (
    "fmt"
    "github.com/samber/lo"
)

func main() {
    prices := []float64{10.5, 20.3, 5.2}
    total := lo.Sum(prices)
    fmt.Printf("Total: %.2f\n", total) // Total: 36.00
}

Conclusión

La librería lo es una herramienta esencial para cualquier desarrollador Go que quiera escribir código más limpio, eficiente y expresivo. Con funciones como Filter, Map, Reduce y muchas más, puedes olvidarte de los bucles repetitivos y centrarte en la lógica de tu aplicación. Además, al estar basada en genéricos, ofrece total seguridad de tipos. ¡No dudes en integrarla en tu próximo proyecto Go!

Recommendations