Como são estruturados os contextos na linguagem Go?
sobes.tech IA
Resposta da IA
O contexto (context.Context) em Go é usado para transmitir informações sobre prazos, cancelamentos e outros dados entre limites de API. Ele representa uma árvore: cada contexto é filho de outro, exceto o raiz (context.Background() ou context.TODO()).
Os métodos principais da interface context.Context:
Deadline() (deadline time.Time, ok bool): Retorna o prazo do contexto.Done() <-chan struct{}: Retorna um canal que é fechado quando o contexto é cancelado.Err() error: Retorna o erro que causou o cancelamento do contexto.Value(key any) any: Retorna o valor associado à chave no contexto.
São criados com funções do pacote context:
context.Background(): O contexto raiz vazio, usado como base para o processo principal.context.TODO(): Usado como marcador de posição quando não se sabe qual contexto usar.context.WithCancel(parent Context): Cria um contexto filho e uma função de cancelamento.context.WithDeadline(parent Context, d time.Time): Cria um contexto filho com um prazo.context.WithTimeout(parent Context, timeout time.Duration): Cria um contexto filho com um tempo limite.context.WithValue(parent Context, key, val any): Cria um contexto filho com um valor.
Implementações principais de Context:
emptyCtx: Básico, não cancelável e sem valores. UsaBackgroundeTODO.cancelCtx: Suporta cancelamento. Consiste em um contexto base e um canal de cancelamento.timerCtx: Suporta prazo/tempo limite. ContémcancelCtxe um temporizador.valueCtx: Suporta transmissão de valores. Contém um contexto base e pares chave-valor.
Ao cancelar o contexto pai, todos os filhos são cancelados automaticamente. Isso permite propagar sinais de cancelamento ou prazos na cadeia de chamadas.
Exemplo de uso de context.WithCancel:
package main
import (
"context"
"fmt"
"time"
)
func main() {
// Cria o contexto raiz e a função de cancelamento
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // Garante o cancelamento ao sair de main
go func() {
select {
case <-ctx.Done(): // Aguarda o cancelamento do contexto
fmt.Println("Tarefa cancelada:", ctx.Err())
return
case <-time.After(5 * time.Second): // Ou termina em 5 segundos
fmt.Println("Tarefa concluída")
}
}()
// Cancela o contexto de outro lugar
time.Sleep(1 * time.Second)
fmt.Println("Cancelando o contexto...")
cancel()
// Dá tempo para a goroutine processar o cancelamento
time.Sleep(100 * time.Millisecond)
}
Exemplo de uso de context.WithValue:
package main
import (
"context"
"fmt"
)
type userIDKey string
func processRequest(ctx context.Context) {
if userID, ok := ctx.Value(userIDKey("UserID")).(string); ok {
fmt.Println("Processando requisição para User ID:", userID)
} else {
fmt.Println("User ID não encontrado no contexto")
}
}
func main() {
ctx := context.WithValue(context.Background(), userIDKey("UserID"), "12345")
processRequest(ctx)
}
Os contextos são seguros para uso concorrente e imutáveis, o que é importante para código concorrente. Eles não são destinados a transmitir parâmetros brutos de funções, mas sim para metainformação que influencia a execução do processo.