Pular para o conteúdo principal

victorstein.dev

42/100 Dias de Golang - Webservers em Go com a Biblioteca Padrão

Table of Contents

# Webservers em Go com a Biblioteca Padrão

Como vimos até aqui Go possui ótimas bibliotecas na própria linguagem, vamos ver como funciona a net/http, que podemos usar para criar webservers. Vamos criar um webserver com uma rota que retorna um “Olá Mundo”.

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", homeHandler)
    fmt.Println("Servidor rodando na porta 8080...")
    http.ListenAndServe(":8080", nil)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Olá Mundo!")
}

Olhe como é simples! http.HandleFunc("/", homeHandler) definimos o path da rota e a função que será executada, nesse caso a homeHandler. E depois depois deixamos o serviço escutando na porta 8080 http.ListenAndServe(":8080", nil). Fechou! Se você entrar no http://localhost:8080/ vai ver a mensagem “Olá Mundo!”. Claro que esse exemplo é “ridículo”, mas veja a estrutura geral, muito simples! Vamos evoluir esse exemplo.

# Parâmetros de Query

Vamos ver como ler query params, esses são os parâmetros passados após o ? na URL, por exemplo: /user?id=123.

func userHandler(w http.ResponseWriter, r *http.Request) {
	id := r.URL.Query().Get("id")
	w.Write([]byte("ID recebido: " + id))
}

E lembre de registar a rota com http.HandleFunc("/user/", userHandler). Aí podemos acessar a rota pela URL: http://localhost:8080/user/?id=12

# JSON

Vamos retornar um JSON agora, aqui vamos usar um conhecimento já visto 021 - Uso de JSON no Golang. Vou criar uma struct com as tags e retornar no handler. Veja que definimos um header w.Header().Set("Content-Type", "application/json") e fazemos o encode do user com json.NewEncoder(w).Encode(user)

type User struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

func jsonHandler(w http.ResponseWriter, r *http.Request) {
	user := User{
		ID:    1,
		Name:  "Victor Stein",
		Email: "victor@stein.dev",
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(user)
}

Veja que em todos os handlers nada é retornado e que em todos os handlers temos os parâmetros w http.ResponseWriter, r *http.Request. O w http.ResponseWriter é usado para construir e enviar a resposta HTTP e o r *http.Request serve para acessar todos os detalhes da requisição HTTP recebida.

Veja essa esse handler com vários tipos de requests:

func resourceHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        w.Write([]byte("GET - Recurso encontrado"))
    case http.MethodPost:
        w.WriteHeader(http.StatusCreated)
        w.Write([]byte("POST - Recurso criado"))
    case http.MethodPut:
        w.Write([]byte("PUT - Recurso atualizado"))
    case http.MethodDelete:
        w.WriteHeader(http.StatusNoContent)
    default:
        w.WriteHeader(http.StatusMethodNotAllowed)
    }
}

Fazemos um switch no r.Method. Caso ele seja GET, executa uma operação, caso seja POST executa outra, … Perceba que escrevemos no header o status de retorno do request: w.WriteHeader(http.StatusCreated) ou w.WriteHeader(http.StatusMethodNotAllowed).

A lib padrão do go fornece diversos outros recursos para criarmos webservers. Além dela temos várias bibliotecas externas quie abstraem várias tarefas!