Visão Geral das Famílias de Pacotes database/sql & net
Go divide redes e SQL em pacotes em camadas que compartilham padrões de context e io.
Busque em todas as páginas da documentação
Go divide redes e SQL em pacotes em camadas que compartilham padrões de context e io.
database/sql gerencia pools de conexão e transações.
A família net (net, net/http, net/url, net/netip) lida com endereços, HTTP e tipos IP modernos.
Importe um driver SQL anonimamente, abra um *sql.DB e configure limites de pool para o SLA do seu banco de dados.
Servidores e clientes HTTP construídos sobre net/http reutilizam as mesmas práticas de tempo limite e contexto das consultas SQL.
Use net/netip para IPs e prefixos tipados em vez de analisar strings ad hoc.
Cartão de receita de referência rápida - pronto para copiar e colar.
import (
"context"
"database/sql"
_ "github.com/jackc/pgx/v5/stdlib"
"net/http"
"time"
)
db, _ := sql.Open("pgx", dsn)
db.SetMaxOpenConns(25)
db.SetConnMaxLifetime(30 * time.Minute)
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
row := db.QueryRowContext(ctx, `SELECT name FROM users WHERE id=$1`, id)
})Quando usar isso:
net.Conn.package main
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"net"
"net/http"
"time"
_ "modernc.org/sqlite"
)
func main() {
db, err := sql.Open("sqlite", "file:users.db?cache=shared&mode=rwc")
if err != nil {
panic(err)
}
defer db.Close()
db.SetMaxOpenConns(1) // sqlite single-writer
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)`); err != nil {
panic(err)
}
if _, err := db.Exec(`INSERT OR IGNORE INTO users (id, name) VALUES (1, 'Ada')`); err != nil {
panic(err)
}
mux := http.NewServeMux()
mux.HandleFunc("/users/", func(w http.ResponseWriter, r *http.Request) {
handleUser(db, w, r)
})
srv := &http.Server{
Addr: ":8080",
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
}
fmt.Println("listening", srv.Addr)
panic(srv.ListenAndServe())
}
func handleUser(db *sql.DB, w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
http.Error(w, "bad remote addr", http.StatusInternalServerError)
return
}
var name string
err = db.QueryRowContext(ctx, `SELECT name FROM users WHERE id=1`).Scan(&name)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]string{
"name": name,
"peer": host,
})
}O que isso demonstra:
sql.Open com importação de driver e ajuste de pool.QueryRowContext respeitando prazos de requisição.net.SplitHostPort para metadados do peer.http.Server voltado para produção com ReadHeaderTimeout.sql.Open cria um handle de pool; a primeira conexão real abre na primeira consulta.database/sql/driver; pgx, mysql e sqlite são distribuídos como módulos.net.Dialer e net.Listen gerenciam sockets TCP/UDP; http.Server adiciona análise HTTP por cima.context fecha consultas em andamento e o trabalho do manipulador HTTP quando os prazos são atingidos.| Pacote | Responsabilidade | Combinação Típica |
|---|---|---|
database/sql | Pool, Tx, Stmt | Módulo driver (pgx, go-sql-driver/mysql) |
net | IPs, dial, listen | Protocolos personalizados, gRPC sobre TCP |
net/http | Servidor/cliente HTTP | Gateways REST, webhooks |
net/url | Análise/construção de URL | Redirecionamentos, strings de consulta |
net/netip | Addr Tipada, Prefixo | Verificações de ACL, roteamento CIDR |
// Sempre pingar após Open para capturar DSN incorreto cedo:
if err := db.PingContext(ctx); err != nil { return err }
// Declarações preparadas para consultas frequentes:
stmt, err := db.PrepareContext(ctx, `SELECT ...`)
// Prefira netip a net.ParseIP para comparações:
addr, _ := netip.ParseAddr("203.0.113.1")sql.Open sem Ping - DSN mal configurado falha na primeira requisição. Correção: PingContext durante verificações de integridade de inicialização.SetMaxOpenConns ilimitado - Esgota conexões de banco de dados sob carga de pico. Correção: defina conexões abertas e ociosas máximas a partir de fórmulas de capacidade do DB.http.DefaultClient em servidores - Sem tempos limite em chamadas de saída. Correção: http.Client dedicado por upstream com ajuste de Transport.rows.Err() após iteração - Resultados parciais silenciosos. Correção: verifique err após o loop for rows.Next().*sql.Tx em structs - Vazamentos de transações entre requisições. Correção: mantenha transações no escopo do manipulador ou método de serviço.net/netip.ParseAddr ou net.SplitHostPort.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| ORM (gorm, ent) | Modelos e migrações complexos | SQL simples com poucas tabelas |
pgx pool diretamente | Recursos avançados apenas para PostgreSQL | Necessita portabilidade database/sql |
gRPC (google.golang.org/grpc) | Contratos RPC internos | APIs JSON voltadas para o navegador |
database/sql + sqlc | Geração de código de consulta tipo-seguro | Apenas SQL dinâmico ad hoc |
Drivers se registram em database/sql em init.
A importação em branco vincula o driver sem referenciar seu pacote diretamente.
sql.DB é um pool de conexões compartilhado entre goroutines.
sql.Tx vincula uma sessão transacional; não compartilhe entre requisições.
Passe r.Context() para QueryContext.
Quando o prazo de leitura/escrita do servidor expirar, o contexto cancela e o driver deve parar a consulta.
Sempre que comparar, analisar ou armazenar endereços IP e prefixos CIDR.
Evita mutabilidade e bugs de análise na forma de slice net.IP.
Não automaticamente.
Implemente retentativas na camada de aplicação para erros transitórios, com backoff e guardas de idempotência.
Servidores HTTP aceitam conexões via net.Listener, então analisam HTTP por cima.
Protocolos personalizados podem usar net.Dial e net.Conn sem HTTP.
O exemplo usa modernc.org/sqlite com um URI file:.
As strings DSN específicas do driver diferem; consulte a documentação do driver para PostgreSQL e MySQL.
Sempre prefira QueryContext em servidores para que o cancelamento se propague.
Query puro usa context.Background() internamente.
Injete um cliente configurado de main em manipuladores ou em uma struct de serviço.
Ajuste Transport.MaxIdleConnsPerHost por dependência upstream.
Cada chamada sql.Open usa um nome de driver.
Bancos de dados diferentes significam handles *sql.DB diferentes, geralmente serviços diferentes.
Analisar URLs de requisição, construir destinos de redirecionamento e codificar parâmetros de consulta sem concatenação manual de strings.
Exponha /health que executa db.PingContext com um tempo limite curto.
Falhe na prontidão quando o pool não conseguir alcançar o banco de dados primário.
Versões da Pilha: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, go fix modernizers - verifique o patch na compilação), chi (última - verifique na compilação), gin (última - verifique na compilação), echo (última - verifique na compilação), google.golang.org/grpc (última - verifique na compilação), sigs.k8s.io/controller-runtime (última - verifique na compilação), kubebuilder (última - verifique na compilação), tinygo (última - verifique os alvos de placa na compilação), wazero (última - verifique na compilação) e golangci-lint (última - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026