context em database/sql & gRPC
database/sql e google.golang.org/grpc foram projetados em torno de context.Context desde o início.
Busque em todas as páginas da documentação
database/sql e google.golang.org/grpc foram projetados em torno de context.Context desde o início.
Passar ctx para métodos de query e RPC vincula o trabalho de banco de dados e rede à mesma árvore de cancelamento do seu handler HTTP.
Use QueryContext, ExecContext e BeginTx com context para cada chamada de banco de dados com escopo de requisição.
Métodos de cliente e servidor gRPC aceitam ctx como o primeiro argumento; deadlines se propagam como timeouts de RPC.
RPCs de streaming devem verificar ctx.Done() entre chamadas Recv e Send.
Cartão de receita de referência rápida - pronto para copiar e colar.
func GetOrder(ctx context.Context, db *sql.DB, id string) (string, error) {
var status string
err := db.QueryRowContext(ctx, `SELECT status FROM orders WHERE id = ?`, id).Scan(&status)
return status, err
}Quando usar isso:
Query/Exec sem Context em qualquer caminho de código alcançável a partir de handlers HTTP ou gRPC.ctx.Done() disparar para evitar vazamentos de goroutine.package main
import (
"context"
"database/sql"
"fmt"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
_ "github.com/mattn/go-sqlite3"
)
func queryStatus(ctx context.Context, db *sql.DB) (string, error) {
ctx, cancel := context.WithTimeout(ctx, 200*time.Millisecond)
defer cancel()
var s string
err := db.QueryRowContext(ctx, `SELECT 'shipped'`).Scan(&s)
return s, err
}
func dialGRPC(ctx context.Context) (*grpc.ClientConn, error) {
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
return grpc.DialContext(ctx, "localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
}
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
parent, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
status, err := queryStatus(parent, db)
fmt.Println(status, err)
_, err = dialGRPC(parent)
fmt.Println("grpc dial:", err)
}O que isso demonstra:
QueryRowContext respeita o cancelamento pai e o timeout filho local.grpc.DialContext bloqueia apenas até o context terminar ou a conexão ser bem-sucedida.database/sql passa o context para interfaces QueryerContext do driver; o comportamento de cancelamento depende do suporte do driver.ctx termina em vez de bloquear para sempre.Tx usam BeginTx(ctx, opts); commit e rollback são rápidos, mas instruções em andamento já devem usar o context da tx.codes.DeadlineExceeded quando o tempo restante for insuficiente.| Método | Variante de Context |
|---|---|
| Query | QueryContext |
| Exec | ExecContext |
| Prepare | PrepareContext |
| Begin | BeginTx(ctx, *TxOptions) |
| Ping | PingContext |
func consume(stream pb.Service_StreamServer) error {
ctx := stream.Context()
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
msg, err := stream.Recv()
if err != nil {
return err
}
_ = msg
}
}Streams de servidor expõem Context(); streams de cliente aceitam o ctx do chamador na invocação inicial do RPC.
Chamadas de cliente Kubernetes de reconciliadores devem passar o context de reconciliação para requisições de API para que os watches parem quando o manager for desligado.
BeginTx com ctx; manter transações curtas.select em ctx.Done() ou lidar com erros de Recv prontamente.DialContext com ctx limitado.ctx.Deadline() no lado do servidor e limitar o trabalho.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
db.SetConnMaxLifetime | Higiene do Pool | Cancelamento por requisição (usar ctx) |
statement_timeout SQL | Limite de query agnóstico ao driver | Substituir completamente o ctx da aplicação |
| gRPC keepalive | Detectar conexões mortas | Aplicação de deadline voltada para o usuário |
| Sessão ORM sem ctx | Jobs em lote internos legados | Handlers de requisição online |
| Fila de mensagens para trabalho lento | Processamento de minutos | Leituras voltadas para o usuário em sub-segundos |
A maioria dos drivers modernos suporta; verifique para seu banco de dados na documentação do driver.
Combine com timeouts em nível de SQL como uma rede de segurança.
Sim para caminhos de requisição - esperar por uma conexão livre deve respeitar o cancelamento do cliente.
Use metadata.NewOutgoingContext em clientes e leia de metadata.FromIncomingContext em servidores.
Mantenha os metadados pequenos e seguros para rede.
Passe ctx para a chamada inicial Client; verifique ctx.Done() entre os chunks de Send.
Sim - contexts são seguros para leituras concorrentes.
Use transações separadas para escritas que precisam de isolamento.
errgroup.WithContext cancela irmãos quando uma query falha.
Passe o ctx do grupo para cada QueryContext.
Migrações de longa duração podem usar context.Background() com cancelamento controlado por ops.
Handlers de requisição online não devem executar migrações.
Mapeie context.Canceled para abortamento do cliente; DeadlineExceeded para respostas de timeout.
Não os trate como 500 genéricos quando o cliente iniciou a parada.
PrepareContext respeita ctx; stmts em cache ainda executam com QueryContext por chamada.
Interceptores unários e de stream podem impor deadlines e anexar valores antes que os handlers sejam executados.
Compartilhe lógica entre middlewares HTTP e gRPC sempre que possível.
Versões de Stack: Esta página foi escrita para Go 1.26.x (padrão GC Green Tea, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026