Como utilizar o framework Echo

Mesmo sem saber ainda se será uma série ou não, nesse post, trago uma visão geral sobre um dos frameworks mais populares do mundo Go, o Echo.

Em sua documentação, o framework Echo se autodenomina como de alta performance, extensível e minimalista. Além dessas características, podemos dizer também que é de fácil implementação. Veja o exemplo abaixo.

package main

import (
    "net/http"
    
    "github.com/labstack/echo/v4"
)

func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })
    e.Logger.Fatal(e.Start(":1323"))
}
  1. Primeiro, iniciamos o framework com um echo.New();
  2. Em seguida, criamos um endpoint para receber requests do tipo GET e.GET("/"....;
  3. No endpoint, definimos que, ao receber uma request, vamos responder com um status 200 e o texto Hello, World! em plain/text;
  4. Por fim, iniciamos o servidor e.Start(":1323").

Ou seja, em 4 simples passos, implementamos uma API.

Rotas e parâmetros

É claro que, para a implementação de uma API no mundo real, o exemplo acima não ajuda muito.

Para ter uma ideia melhor do quanto um framework facilitará a implementação de uma API no mundo real, precisamos saber, pelo menos, como passar e pegar parâmetros através das rotas.

No exemplo abaixo, podemos ver uma simples implementação para a rota /users/ID-DO-USER.

// routes.go
e.GET("/users/:id", getUser)

// get.go
func getUser(c echo.Context) error {
  id := c.Param("id")
	...
}

Caso o parâmetro seja passado por query string, por exemplo em uma busca, utilize o c.QueryParam("PARAM_NAME") para obter o valor passado na URL.

Formulários

Seja application/x-www-form-urlencoded ou multipart/form-data, o framework Echo fornece vários métodos para nos auxiliar no parse de payload.

Para obter os valores passados no campo de um formulário (application/x-www-form-urlencoded), utilizamos o método c.FormValue("FIELD-NAME").

No exemplo abaixo, mostro como lidar com formulários que contém upload de arquivos (multipart/form-data).

func save(c echo.Context) error {
  // Obtém valor do campo "name"
  name := c.FormValue("name")
  // Obtém informações do campo de upload "avatar"
  avatar, err := c.FormFile("avatar")
  if err != nil {
    return err
  }
 
  // Obtém o source
  src, err := avatar.Open()
  if err != nil {
    return err
  }
  defer src.Close()
 
  // Cria o destination
  dst, err := os.Create(avatar.Filename)
  if err != nil {
    return err
  }
  defer dst.Close()
 
  // Copia os dados do source para o destination
  if _, err = io.Copy(dst, src); err != nil {
    return err
  }
		
	...
}

Requests

E o que seria de um framework web, sem um método para fazer parse do payload de uma request?

No Echo, temos o método Bind, que é capaz de fazer parse de json, xml, form e query. Esse método as tags adicionadas aos atributos de uma struct para fazer o match entre o dado da request e o campo da struct.

type User struct {
    Name  string `json:"name" xml:"name" form:"name" query:"name"`
    Email string `json:"email" xml:"email" form:"email" query:"email"`
}

e.POST("/users", func(c echo.Context) error {
    u := new(User)
    if err := c.Bind(u); err != nil {
        return err
    }
    return c.JSON(http.StatusCreated, u)
    // or
    // return c.XML(http.StatusCreated, u)
})

Já para as responses, contamos com os métodos JSON e XML. Como podemos ver acima, ambos precisam de dois parâmetros, sendo o primeiro o status code e o segundo o body.

Middleware

Se você não tem familiaridade com o termo, para frameworks web, um middleware é uma funcionalidade que você adiciona entre a entrada da request e a função que irá tratá-la.

Um exemplo de middleware, é a validação de um token JWT em uma request autenticada.

Assim como outros frameworks web, o Echo disponibiliza uma série de middlewares prontos, como:

Na documentação do framework tem uma lista completa de middleware.

Conclusão

Embora eu não tenha tido nenhuma experiência utilizando Echo em produção, pelo que já vi de amigos utilizando, ele parece ser bem robusto.

Um “problema” que ele tem, é o fato de não utilizar a assinatura func(http.ResponseWriter, *http.Request) nas funções que tratam as requests. Coloquei entre aspas, pois esse “problema” só se tornará uma dor caso o time, por qualquer que seja o motivo, resolva remover o Echo da aplicação.

No mais, assim como outros frameworks web minimalistas, boa parte do ciclo de vida de uma request gira em torno da struct Context. Isso facilita muito a implementação de uma API, pois não há a necessidade de utilizar vários packages para tratar a request e response.

Me conta nos comentários se você já utilizou esse framework em produção e qual foi a sua experiência.

Ahh… também não esquece de assinar a newsletter! Além de ganhar um cupom de 20% de desconto nos cursos e na imersão do Aprenda Golang, a cada 15 dias, envio algum conteúdo que não sai em nenhum outro canal. Na última edição falamos sobre “Utilizar ou não DTOs em projetos Go”.

Até a próxima!


Se inscreva na nossa newsletter

* indicates required

Deixe uma resposta