Introdução: por que Go é a escolha ideal para REST API
Go (Golang) é uma linguagem de programação compilada, criada no Google para sistemas de alta carga. Ela combina a velocidade do C, a simplicidade do Python e suporte nativo a concorrência. Para criar REST APIs, Go oferece a poderosa biblioteca padrão net/http e frameworks populares como gorilla/mux e gin.
Neste guia, em 30 minutos criaremos uma REST API completa para gerenciar uma lista de tarefas (Todo List) em Go puro, sem frameworks de terceiros. Você aprenderá a:
- Configurar roteamento e handlers
- Trabalhar com JSON (serialização/desserialização)
- Implementar operações CRUD (Create, Read, Update, Delete)
- Adicionar middleware para logging e CORS
Todo o código será escrito em um único arquivo main.go para simplificar. Vamos começar!
Passo 1: Estrutura básica e inicialização do servidor HTTP
Crie o arquivo main.go e adicione o código a seguir. Declararemos a estrutura de dados para a tarefa e iniciaremos um servidor simples.
package main
import ( "encoding/json" "log" "net/http" "strconv" "strings" "sync" "time")
// Task — estrutura da tarefatype Task struct { ID int `json:"id"` Title string `json:"title"` Completed bool `json:"completed"` CreatedAt time.Time `json:"created_at"`}
// Armazenamento de tarefas (in-memory)var ( tasks = make(map[int]Task) nextID = 1 mu sync.Mutex)
func main() { // Rotas http.HandleFunc("/api/tasks", tasksHandler) http.HandleFunc("/api/tasks/", taskByIDHandler)
log.Println("Servidor iniciado na porta :8080") log.Fatal(http.ListenAndServe(":8080", nil))}Explicação:
Task— estrutura com tags JSON para serialização correta.tasks— mapa para armazenar tarefas em memória (sem banco de dados).mu— mutex para acesso seguro a partir de goroutines.- Duas rotas:
/api/tasks(listar e criar) e/api/tasks/(trabalhar com uma tarefa por ID).
Passo 2: Handlers para lista de tarefas (GET e POST)
Implementaremos a função tasksHandler, que processa GET (obter todas as tarefas) e POST (criar nova tarefa).
func tasksHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json")
switch r.Method { case http.MethodGet: mu.Lock() taskList := make([]Task, 0, len(tasks)) for _, task := range tasks { taskList = append(taskList, task) } mu.Unlock() json.NewEncoder(w).Encode(taskList)
case http.MethodPost: var newTask Task if err := json.NewDecoder(r.Body).Decode(&newTask); err != nil { http.Error(w, `{"error":"JSON inválido"}`, http.StatusBadRequest) return } mu.Lock() newTask.ID = nextID nextID++ newTask.CreatedAt = time.Now() tasks[newTask.ID] = newTask mu.Unlock()
w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(newTask)
default: http.Error(w, `{"error":"Método não suportado"}`, http.StatusMethodNotAllowed) }}Pontos-chave:
- Usamos
json.NewEncoderejson.NewDecoderpara trabalhar com JSON. - No POST, verificamos a validade do JSON, atribuímos o ID e retornamos 201 Created.
- O mutex protege os dados durante acesso concorrente.
Passo 3: Handlers para tarefa individual (GET, PUT, DELETE)
Agora implementaremos taskByIDHandler. Extraímos o ID da URL usando strings.TrimPrefix