Biblioteca mo para Go: Monads e Padrões Funcionais
Bem-vindo ao mundo da programação funcional em Go! A biblioteca mo (de monads) é uma ferramenta poderosa que traz para a linguagem imperativa Go os conceitos de monads e padrões funcionais populares em Haskell, Scala e Rust. Se você já enfrentou o problema de tratar erros com if err != nil, verificações aninhadas intermináveis de nil ou cadeias de chamadas complexas, o mo oferece uma solução elegante.
O principal objetivo da biblioteca é fornecer contêineres type-safe (Option, Result, Either) que encapsulam estados possíveis (presença/ausência de valor, sucesso/erro) e permitem trabalhar com eles de forma funcional. Em vez de escrever dezenas de condicionais, você constrói cadeias de transformações onde cada etapa é tratada automaticamente. Isso torna o código mais legível, previsível e menos propenso a erros, especialmente em lógicas de negócio complexas.
A biblioteca mo não tenta transformar Go em Haskell. Ela oferece uma abordagem pragmática: você usa padrões funcionais onde eles realmente simplificam o código, mantendo a sintaxe familiar do Go. O mo é especialmente útil para tratamento de erros, trabalho com valores opcionais, composição de funções e implementação de pipelines de processamento de dados. Ele se integra bem com goroutines e canais, permitindo construir programas concorrentes robustos.
Instalação
A instalação da biblioteca mo segue o padrão do Go usando o gerenciador de pacotes go get. Execute o seguinte comando no terminal na raiz do seu projeto (onde está o arquivo go.mod):
go get github.com/samber/mo
Após executar este comando, a biblioteca será adicionada ao seu arquivo go.mod e você poderá importá-la nos seus arquivos de código. Certifique-se de ter a versão Go 1.18 ou superior (necessária para suporte a genéricos).
Início Rápido
Vamos começar com um exemplo clássico: a divisão segura de dois números. No Go tradicional, retornaríamos um erro. Com o mo, usamos o tipo Result, que pode ser Ok (sucesso) ou Err (erro).
package main
import (
"fmt"
"github.com/samber/mo"
)
// safeDivide retorna um Result que contém o resultado da divisão ou um erro.
func safeDivide(a, b float64) mo.Result[float64] {
if b == 0 {
return mo.Err[float64](fmt.Errorf("divisão por zero"))
}
return mo.Ok(a / b)
}
func main() {
result := safeDivide(10, 2)
// Usamos o método Match para tratar ambos os casos.
result.Match(
func(value float64) {
fmt.Printf("Resultado: %.2f\n", value)
},
func(err error) {
fmt.Printf("Erro: %s\n", err)
},
)
// Vamos tentar a divisão por zero.
result2 := safeDivide(10, 0)
result2.Match(
func(value float64) {
fmt.Printf("Resultado: %.2f\n", value)
},
func(err error) {
fmt.Printf("Erro: %s\n", err)
},
)
}
Este exemplo demonstra a ideia básica: em vez de verificar o erro manualmente, delegamos o tratamento à biblioteca usando o método Match.
Métodos e Funções Principais
Abaixo estão os principais componentes da biblioteca mo. Vamos abordar 8 métodos/tipos essenciais que cobrirão 90% das suas necessidades.
1. mo.Ok[T any] e mo.Err[T any]
Assinatura:
func Ok[T any](value T) Result[T]func Err[T any](err error) Result[T]
O que faz: Criam e