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!