No desenvolvimento de aplicações em Go, é comum enfrentar situações em que precisamos gerenciar o tempo de vida de processos, propagar cancelamentos de tarefas ou passar dados entre goroutines.
Para resolver esses problemas, a própria linguagem fornece um package chamado context.
Nesse post, vamos explorar juntos o que é o package context, para que ele serve, onde normalmente é utilizado e como implementá-lo em suas aplicações Go.
Hello Context
O package context foi introduzido na versão 1.7 do Go e é utilizado para gerenciar deadlines, cancelamentos e outros valores através de limites de API e entre goroutines. Sua principal função é gerenciar o tempo de vida de uma operação, especialmente em servidores e aplicativos web, onde operações longas podem ser canceladas se excederem um determinado tempo ou se a solicitação do cliente for cancelada.
Utilização
- Propagação de cancelamento: Permite que uma operação em execução possa ser cancelada. Um exemplo seria cancelar a execução da goroutine B se a execução da goroutine A falhar.
- Deadlines e timeouts: Define um tempo máximo de execução para uma operação. Normalmente utilizado para controlar requests à APIs ou conexão com bancos de dados, queues e etc.
- Transporte de dados entre processos: Facilita o compartilhamento de dados específicos de uma solicitação entre funções, como por exemplo a opção
Request.Context()do packagenet/http.
Context na prática
Para entender melhor sua utilização, no exemplo abaixo, utilizamos o context para controlar o timeout de uma request, onde, caso a operação não seja concluída em 2 segundos, a requisição será cancelada.
package main
import (
"context"
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
// Cria um context com timeout de 2 segundos
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel() // Assegura que o cancelamento seja chamado
// ... código para executar algo
select {
case <-ctx.Done():
// Timeout ou cancelamento
http.Error(w, "Request cancelada ou timeout", http.StatusRequestTimeout)
case result := <-resultChan:
// Resultado com sucesso!
fmt.Fprintln(w, result)
}
}
Outro exemplo seria fornecer o context como um parâmetro de uma função, para que cada chamada à ela defina suas condições de cancelamento/timeout.
package main
import (
"context"
"fmt"
"time"
)
// Função que realiza uma tarefa longa
func longRunningTask(ctx context.Context) (string, error) {
resultChan := make(chan string, 1)
go func() {
// Simula uma operação longa
time.Sleep(5 * time.Second)
resultChan <- "Tarefa completa"
}()
select {
case <-ctx.Done():
// Operação foi cancelada ou houve timeout
return "", ctx.Err()
case result := <-resultChan:
return result, nil
}
}
Boas práticas
- Cancele contexts explicitamente: Sempre chame a função
cancelpara liberar recursos. - Evite o uso de
context.Backgroundecontext.TODO: Utilize-os apenas em testes ou funções principais. - Passe context como primeiro parâmetro: Siga a convenção de passar o contexto como o primeiro argumento em funções.
- Evite armazenar context em structs: Contextos devem ser passados explicitamente para funções e não armazenados em structs para evitar vazamento de memória.
Conclusão
O package context é uma ferramenta poderosa no arsenal de um desenvolvedor Go, proporcionando controle eficiente sobre o tempo de vida de operações e facilitando o gerenciamento de cancelamentos e deadlines. Seguindo as boas práticas, você pode garantir que suas aplicações sejam mais robustas, responsivas e eficientes.
Se você quer saber mais sobre o package context, leia também:
Assine nossa newsletter e receba os conteúdos do blog toda semana diretamente na sua caixa de e-mail.
Até a próxima!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.
Livros Recomendados
Abaixo listei alguns dos melhores livros que já li sobre GO.





[…] O que é e como utilizar o package context […]