Introdução: Por que Go e bancos de dados são a combinação ideal
A linguagem de programação Go (Golang) ganhou popularidade devido ao seu alto desempenho, suporte integrado para concorrência e facilidade de implantação. No entanto, o verdadeiro poder do Go se revela ao trabalhar com bancos de dados. Seja o relacional PostgreSQL ou o orientado a documentos MongoDB, o Go oferece ferramentas elegantes para interação eficiente com dados.
Neste artigo, abordaremos os aspectos práticos de conexão, execução de operações CRUD e otimização de consultas para PostgreSQL e MongoDB em Go. Você aprenderá a usar pacotes padrão e drivers populares para escrever código confiável e rápido.
1. Trabalhando com PostgreSQL em Go
Para trabalhar com PostgreSQL em Go, utiliza-se o pacote padrão database/sql em conjunto com o driver pgx ou lib/pq. O pgx é recomendado devido ao melhor desempenho e suporte a recursos avançados do PostgreSQL.
1.1. Instalação e conexão
Instale o driver via go modules:
go get github.com/jackc/pgx/v5Exemplo de conexão ao banco de dados:
package main
import ( "context" "fmt" "github.com/jackc/pgx/v5/pgxpool" "log")
func main() { dsn := "postgres://user:password@localhost:5432/mydb?sslmode=disable" pool, err := pgxpool.New(context.Background(), dsn) if err != nil { log.Fatal("Unable to connect to database:", err) } defer pool.Close()
fmt.Println("Connected to PostgreSQL!")}Dica: Use um pool de conexões (pgxpool) para ambiente de produção — isso reduz a sobrecarga de estabelecer novas conexões.
1.2. Operações CRUD
Vamos considerar as operações básicas usando a tabela users como exemplo:
// CREATEfunc createUser(pool *pgxpool.Pool, name string, email string) (int, error) { var id int err := pool.QueryRow(context.Background(), "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id", name, email).Scan(&id) if err != nil { return 0, err } return id, nil}
// READfunc getUser(pool *pgxpool.Pool, id int) (string, string, error) { var name, email string err := pool.QueryRow(context.Background(), "SELECT name, email FROM users WHERE id = $1", id).Scan(&name, &email) if err != nil { return "", "", err } return name, email, nil}
// UPDATEfunc updateUserEmail(pool *pgxpool.Pool, id int, newEmail string) error { _, err := pool.Exec(context.Background(), "UPDATE users SET email = $1 WHERE id = $2", newEmail, id) return err}
// DELETEfunc deleteUser(pool *pgxpool.Pool, id int) error { _, err := pool.Exec(context.Background(), "DELETE FROM users WHERE id = $1", id) return err}Observe o uso de consultas parametrizadas com $1, $2 — isso protege contra injeção de SQL.
1.3. Transações
O PostgreSQL suporta transações, o que é crítico para a integridade dos dados:
func transferMoney(pool *pgxpool.Pool, fromID, toID int, amount float64) error { tx, err := pool.Begin(context.Background()) if err != nil { return err } defer tx.Rollback(context.Background()) // reversão em caso de erro
_, err = tx.Exec(context.Background(), "UPDATE accounts SET balance = balance - $1 WHERE id = $2", amount, fromID) if err != nil { return err }
_, err = tx.Exec(context.Background(), "UPDATE accounts SET balance = balance + $1 WHERE id = $2", amount, toID) if err != nil { return err }
return tx.Commit(context.Background())}2. Trabalhando com MongoDB em Go
MongoDB — documento