Demonstração de Cancelamento de Contexto em Golang

Beginner

This tutorial is from open-source community. Access the source code

Introdução

Este laboratório tem como objetivo demonstrar o uso de context.Context para controlar o cancelamento em Golang. Um Context carrega prazos, sinais de cancelamento e outros valores com escopo de requisição através de limites de API e goroutines.

Context (Contexto)

A função hello simula algum trabalho que o servidor está fazendo, esperando alguns segundos antes de enviar uma resposta ao cliente. Enquanto trabalha, fique de olho no canal Done() do contexto para um sinal de que devemos cancelar o trabalho e retornar o mais rápido possível.

  • Versão Golang 1.13 ou superior.
## Execute o servidor em segundo plano.
$ go run context-in-http-servers.go &

## Simule uma requisição do cliente para `/hello`, pressionando
## Ctrl+C logo após iniciar para sinalizar
## o cancelamento.
$ curl localhost:8090/hello
server: hello handler started
^C
server: context canceled
server: hello handler ended

A seguir, o código completo:

// No exemplo anterior, analisamos a configuração de um simples
// [servidor HTTP](http-servers). Servidores HTTP são úteis para
// demonstrar o uso de `context.Context` para
// controlar o cancelamento. Um `Context` carrega prazos,
// sinais de cancelamento e outros valores com escopo de requisição
// através de limites de API e goroutines.
package main

import (
	"fmt"
	"net/http"
	"time"
)

func hello(w http.ResponseWriter, req *http.Request) {

	// Um `context.Context` é criado para cada requisição pelo
	// mecanismo `net/http` e está disponível com
	// o método `Context()`.
	ctx := req.Context()
	fmt.Println("server: hello handler started")
	defer fmt.Println("server: hello handler ended")

	// Espere alguns segundos antes de enviar uma resposta ao
	// cliente. Isso poderia simular algum trabalho que o servidor está
	// fazendo. Enquanto trabalha, fique de olho no canal
	// `Done()` do contexto para um sinal de que devemos cancelar
	// o trabalho e retornar o mais rápido possível.
	select {
	case <-time.After(10 * time.Second):
		fmt.Fprintf(w, "hello\n")
	case <-ctx.Done():
		// O método `Err()` do contexto retorna um erro
		// que explica por que o canal `Done()` foi
		// fechado.
		err := ctx.Err()
		fmt.Println("server:", err)
		internalError := http.StatusInternalServerError
		http.Error(w, err.Error(), internalError)
	}
}

func main() {

	// Como antes, registramos nosso handler na rota "/hello"
	// e começamos a servir.
	http.HandleFunc("/hello", hello)
	http.ListenAndServe(":8090", nil)
}

Resumo

Neste laboratório, aprendemos como usar context.Context para controlar o cancelamento em Golang. Ao criar um Context com um tempo limite (timeout) e passá-lo para uma função, podemos garantir que a função retorne o mais rápido possível se o tempo limite for excedido.