lo para Go: guia completo com exemplos práticos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Biblioteca lo para Go: Utilitárias Genéricas (Lodash para Go)

No mundo do desenvolvimento em Go, surge frequentemente a necessidade de funções práticas para trabalhar com coleções, como as existentes em outras linguagens (por exemplo, map, filter, reduce do JavaScript ou Python). A biblioteca padrão do Go oferece um conjunto mínimo de ferramentas, e escrever loops for repetitivos para cada operação se torna cansativo. É aqui que a biblioteca lo entra em cena — um poderoso conjunto de utilitárias genéricas, inspirado na popular biblioteca JavaScript Lodash.

A biblioteca lo utiliza genéricos (tipos genéricos), introduzidos no Go 1.18+, para fornecer funções type-safe para trabalhar com slices, maps, channels e outras estruturas de dados. Em vez de escrever for i := range slice { ... } para cada transformação, você pode usar uma única linha de código: lo.Map(slice, transformFunc). Isso torna o código mais legível, conciso e menos propenso a erros.

Por que usar lo? Primeiro, economia de tempo: você para de escrever código boilerplate. Segundo, aumento da confiabilidade: as funções da biblioteca são cuidadosamente testadas e cobrem diversos casos extremos. Terceiro, padronização: toda a equipe usa as mesmas funções com nomes claros, facilitando as revisões de código. lo é um must-have para qualquer projeto Go que lide ativamente com coleções de dados.

Instalação

A instalação da biblioteca lo é feita da forma padrão do Go, através do go get. Certifique-se de ter a versão Go 1.18 ou superior instalada (já que a biblioteca usa genéricos).

go get github.com/samber/lo@latest

Após executar este comando, a biblioteca será adicionada ao seu arquivo go.mod. Agora você pode importá-la no seu código:

import "github.com/samber/lo"

Início Rápido

Vamos escrever um programa simples que usa lo para filtrar e transformar um 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}

    // Filtra apenas os 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]

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

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

Como você pode ver, o código ficou muito mais declarativo e legível. Evitamos escrever três loops for separados.

Principais Métodos e Funções

Abaixo está uma lista das funções-chave da biblioteca lo com exemplos de uso. A maioria das funções recebe um slice e uma função de callback.

1. lo.Filter

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

O que faz: Cria um novo slice contendo apenas os elementos do slice original para os quais a função predicado retornou true.

package main

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

func main() {
    names := []string{"Alice", "Bob", "Charlie", "David", "Eve"}
    // Mantém apenas nomes com mais de 3 caracteres
    longNames := lo.Filter(names, func(name string, _ int) bool {
        return len(name) > 3
    })
    fmt.Println(longNames) // [Alice Charlie David]
}

2. lo.Map

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

O que faz: Transforma cada elemento de um slice usando uma função de iteração e retorna um novo slice com os resultados.

package main

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

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    // Converte cada número para sua representação em string
    stringNumbers := lo.Map(numbers, func(x int, _ int) string {
        return fmt.Sprintf("Número: %d", x)
    })
    fmt.Println(stringNumbers) // [Número: 1 Número: 2 Número: 3 Número: 4 Número: 5]
}

3. lo.Reduce

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

O que faz: Reduz um slice a um único valor acumulado, aplicando uma função acumuladora a cada elemento.

package main

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

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    // Calcula o produto de todos os números
    product := lo.Reduce(numbers, func(agg int, item int, _ int) int {
        return agg * item
    }, 1)
    fmt.Println("Produto:", product) // 120
}

4. lo.Find

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

O que faz: Encontra o primeiro elemento em um slice que satisfaz a condição do predicado. Retorna o elemento e um booleano indicando se foi encontrado.

package main

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

func main() {
    numbers := []int{10, 20, 30, 40, 50}
    // Encontra o primeiro número maior que 25
    found, ok := lo.Find(numbers, func(x int) bool {
        return x > 25
    })
    if ok {
        fmt.Println("Encontrado:", found) // 30
    } else {
        fmt.Println("Número não encontrado")
    }
}

5. lo.Uniq

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

O que faz: Remove elementos duplicados de um slice, mantendo a ordem original.

package main

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

func main() {
    numbers := []int{1, 2, 2, 3, 3, 3, 4, 5, 5}
    unique := lo.Uniq(numbers)
    fmt.Println("Únicos:", unique) // [1 2 3 4 5]
}

6. lo.Chunk

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

O que faz: Divide um slice em pedaços (chunks) de tamanho especificado.

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("Pedaços:", chunks) // [[1 2 3] [4 5 6] [7]]
}

7. lo.Flatten

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

O que faz: Achata um slice de slices em um único slice.

package main

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

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

8. lo.Sum

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

O que faz: Calcula a soma de todos os elementos numéricos em um slice.

package main

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

func main() {
    numbers := []float64{1.5, 2.5, 3.0}
    total := lo.Sum(numbers)
    fmt.Println("Soma total:", total) // 7.0
}

Conclusão

A biblioteca lo é uma ferramenta indispensável para qualquer desenvolvedor Go que queira escrever código mais limpo, eficiente e expressivo. Com suas funções utilitárias genéricas, você pode substituir dezenas de loops manuais por chamadas de função concisas e legíveis. Seja para filtrar, mapear, reduzir ou manipular coleções de dados, lo oferece uma solução elegante e testada.

Comece a usar lo hoje mesmo e veja como seu código Go pode se tornar mais produtivo e agradável de escrever!

Recommendations