Overview de las familias de paquetes database/sql y net
Go divide la red y SQL en paquetes en capas que comparten patrones de context e io.
Busca en todas las páginas de la documentación
Go divide la red y SQL en paquetes en capas que comparten patrones de context e io.
database/sql administra pools de conexiones y transacciones.
La familia net (net, net/http, net/url, net/netip) maneja direcciones, HTTP y tipos IP modernos.
Importe un driver SQL anónimamente, abra un *sql.DB y configure los límites del pool para su SLA de base de datos.
Los servidores y clientes HTTP construidos sobre net/http reutilizan las mismas prácticas de tiempo de espera y contexto que las consultas SQL.
Use net/netip para IPs y prefijos tipados en lugar de analizar cadenas ad hoc.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
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)
})Cuándo usar esto:
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 escritura única
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,
})
}Lo que esto demuestra:
sql.Open con importación de driver y ajuste del pool.QueryRowContext respetando los plazos de las solicitudes.net.SplitHostPort para metadatos del par.http.Server orientado a producción con ReadHeaderTimeout.sql.Open crea un manejador de pool; la primera conexión real se abre en la primera consulta.database/sql/driver; pgx, mysql y sqlite se distribuyen como módulos.net.Dialer y net.Listen administran sockets TCP/UDP; http.Server superpone el análisis HTTP encima.context cierra las consultas en curso y el trabajo del manejador HTTP cuando se alcanzan los plazos.| Paquete | Responsabilidad | Emparejamiento típico |
|---|---|---|
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álisis/construcción de URL | Redirecciones, cadenas de consulta |
net/netip | Addr tipado, Prefijo | Comprobaciones ACL, enrutamiento CIDR |
// Siempre haga ping después de Open para detectar DSN incorrectos temprano:
if err := db.PingContext(ctx); err != nil { return err }
// Sentencias preparadas para consultas frecuentes:
stmt, err := db.PrepareContext(ctx, `SELECT ...`)
// Prefiera netip sobre net.ParseIP para comparaciones:
addr, _ := netip.ParseAddr("203.0.113.1")sql.Open sin Ping - El DSN mal configurado falla en la primera solicitud. Solución: PingContext durante las comprobaciones de estado de inicio.SetMaxOpenConns sin límites - Agota las conexiones de la base de datos bajo carga de picos. Solución: establezca las conexiones abiertas e inactivas máximas a partir de las fórmulas de capacidad de la DB.http.DefaultClient en servidores - Sin tiempos de espera en llamadas salientes. Solución: http.Client dedicado por dependencia externa con ajuste de Transport.rows.Err() después de la iteración - Resultados parciales silenciosos. Solución: compruebe err después del bucle for rows.Next().*sql.Tx en structs - Fugas de transacciones entre solicitudes. Solución: mantenga las transacciones limitadas al manejador o al método del servicio.net/netip.ParseAddr o net.SplitHostPort.| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| ORM (gorm, ent) | Modelos y migraciones complejos | SQL simple con pocas tablas |
Pool pgx directamente | Funciones avanzadas solo de PostgreSQL | Necesita portabilidad de database/sql |
gRPC (google.golang.org/grpc) | Contratos RPC internos | APIs JSON orientadas al navegador |
database/sql + sqlc | Generación de código de consulta tipo seguro | Solo SQL dinámico ad hoc |
Los drivers se registran en database/sql en init.
La importación en blanco enlaza el driver sin referenciar su paquete directamente.
sql.DB es un pool de conexiones compartido entre goroutines.
sql.Tx vincula una sesión transaccional; no compartir entre solicitudes.
Pase r.Context() a QueryContext.
Cuando se dispara el plazo de lectura/escritura del servidor, el contexto se cancela y el driver debería detener la consulta.
Siempre que compare, analice o almacene direcciones IP y prefijos CIDR.
Evita la mutabilidad y los errores de análisis en el formato de slice net.IP.
No automáticamente.
Implemente reintentos en la capa de aplicación para errores transitorios, con retroceso y salvaguardas de idempotencia.
Los servidores HTTP aceptan conexiones a través de net.Listener, luego analizan HTTP encima.
Los protocolos personalizados pueden usar net.Dial y net.Conn sin HTTP.
El ejemplo usa modernc.org/sqlite con una URI file:.
Las cadenas DSN específicas del driver difieren; consulte la documentación del driver para PostgreSQL y MySQL.
Prefiera siempre QueryContext en servidores para que la cancelación se propague.
Query sin contexto usa context.Background() internamente.
Inyecte un cliente configurado desde main en los manejadores o en una estructura de servicio.
Ajuste Transport.MaxIdleConnsPerHost por dependencia externa.
Cada llamada a sql.Open usa un nombre de driver.
Diferentes bases de datos significan diferentes manejadores *sql.DB, generalmente diferentes servicios.
Analizar URLs de solicitud, construir destinos de redirección y codificar parámetros de consulta sin concatenación manual de cadenas.
Exponer /health que ejecuta db.PingContext con un tiempo de espera corto.
Fallar la preparación cuando el pool no puede alcanzar la base de datos principal.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (Predeterminado GC Green Tea, go fix modernizers - verificar parche en la compilación), chi (última - verificar en la compilación), gin (última - verificar en la compilación), echo (última - verificar en la compilación), google.golang.org/grpc (última - verificar en la compilación), sigs.k8s.io/controller-runtime (última - verificar en la compilación), kubebuilder (última - verificar en la compilación), tinygo (última - verificar objetivos de placa en la compilación), wazero (última - verificar en la compilación) y golangci-lint (última - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 16 jul 2026