Compreendendo contextos em Go
O contexto é um dos recursos críticos em Go que permite a simultaneidade. Em Go, “contexto” refere-se a um pacote que fornece funcionalidade para valores com escopo de solicitação e sinais de cancelamento nos limites da API.
O pacote de contexto funciona simultaneamente com o modelo de concorrência do Go, baseado no conceito de goroutines. Goroutines são threads leves de execução que você pode criar e gerenciar com eficiência, facilitando a criação de programas simultâneos em Go.
O pacote de contexto
O pacote de contexto fornece funcionalidade para cancelar funções de execução longa ou cadeias de chamadas inteiras. O pacote também ajuda a armazenar valores com escopo de solicitação para acesso em qualquer lugar dentro da cadeia de chamadas. Esse recurso é útil ao trabalhar com APIs ou microsserviços, onde as solicitações podem abranger várias chamadas de função e você deseja cancelá-las ou anexar valores específicos a elas.
Veja como você pode importar o pacote de contexto em seus programas Go.
import "context"
As funções de contexto aceitam o tipo de estrutura Context do pacote de contexto. Convencionalmente, você deve usar ctx como o nome da variável de instância.
func operations(ctx context.Context) {
}
As funções podem retornar o tipo struct Context para outras funções e operações.
func operations(ctx context.Context) context.Context {
}
Você pode criar um novo contexto com a função TODO do pacote de contexto. A função TODO cria um novo contexto com o valor de context.Done() , um canal que será fechado no cancelamento do contexto. Você deve usá-lo como um espaço reservado quando precisar de um contexto, mas nenhum contexto pai for adequado.
import "context"
func main() {
ctx: = context.TODO()
}
Como alternativa, a função Background cria um novo contexto sem valor e um canal Done vazio.
ctx: = context.Background()
Você deve usar a função Background como raiz de uma árvore de contexto.
Contexto com valores
O pacote de contexto fornece funcionalidade para propagar valores e sinais de cancelamento. Você pode usar os valores para obter informações de dados com escopo de solicitação para sinais de cancelamento e prazos.
O pacote de contexto também permite a criação de contexto filho herdado de contextos pai, permitindo a manipulação eficiente de valores e sinais de cancelamento em todo o programa, pois você pode passar o contexto por várias funções.
Aqui está um exemplo de passagem de contexto através de funções com o pacote context.
import (
"context"
)
func valuableContext(ctx context.Context) context.Context {
return context.WithValue(ctx, "pass-key", "hfouneqcelkwfu")
}
func receiveContextData(ctx context.Context) any {
passKey: = ctx.Value("pass-key")
return passKey
}
A função valueContext recebe uma instância de contexto e retorna uma instância de contexto para a função a seguir. A instância de contexto é um valor criado com o método WithValue . O método WithValue pega a instância de contexto da função e um par chave-valor.
Para recuperar os dados do contexto, você precisará criar um novo contexto com a função TODO ou Background e passar o contexto para a função (neste caso, valueContext) e receber o contexto com a função receiveContextData .
func main() {
ctx: = context.Background()
ctx = valuableContext(ctx)
fmt.Println(receiveContextData(ctx))
}
A variável ctx é a instância de contexto da função Background. A função valueContext recebe a variável ctx e retorna o contexto com um valor que a função receiveContextData recebe e retorna o valor do par chave-valor.
Limites de tempo e prazos de contexto
O pacote de contexto fornece funcionalidade para definir tempos limite e prazos nas operações. Definir tempos limite e prazos é útil para operações que precisam ser atualizadas.
Timeouts são a duração de tempo que uma operação leva. Você pode definir um tempo limite para uma operação de 4 segundos; depois disso, o contexto cancela a solicitação.
Por outro lado, um deadline define o ponto absoluto em que uma operação deve ser cancelada.
Você pode usar o método WithTimeout para definir um tempo limite de contexto. Veja como você pode definir um tempo limite de 2 segundos.
func main() {
ctx, cancel: = context.WithTimeout(context.Background(), 2 * time.Second)
defer cancel()
// some operation
}
A função principal cria um contexto com um tempo limite de dois segundos. A função WithTimeout retorna uma função de cancelamento que você pode adiar para cancelamento na saída da função principal.
Você pode declarar prazos com o método WithDeadline . O método WithDeadline considera uma instância de contexto e um prazo final.
func doSomething(ctx context.Context) {
deadlineTime: = time.Now().Add(1500 * time.Millisecond)
ctx, ctxCancel: = context.WithDeadline(ctx, deadlineTime)
defer ctxCancel()
// some operation
ctxCancel()
}
A função doSomething leva em um contexto, e a variável deadlineTime é o tempo antes do deadline do contexto . A variável ctx é o contexto com um deadline.
A variável ctxCancel cancela o contexto quando o contexto excede seu prazo.
Melhores práticas para usar contextos em Go
Evite usar contextos como variáveis globais. O uso de contextos como variáveis globais pode levar a comportamentos de código inesperados e erros difíceis de rastrear, e use o contexto com moderação para reduzir a complexidade do código.
Finalmente, use contextos como sinais, não como garantias. Cancelar um contexto não garante que todas as goroutines irão parar de rodar; é meramente um sinal, e goroutines são independentes de contextos.
Deixe um comentário