Como utilizar live reload para melhorar sua produtividade

Se você se sente incomodado em ter que parar sua aplicação e fazer go run novamente toda vez que faz uma alteração, esse post vai melhorar sua vida… e MUITO.

Nesse post vou te mostrar como fazer live reload de aplicações Go utilizando uma ferramenta open source chamada Air (https://github.com/cosmtrek/air).

Para testar as funcionalidades da ferramenta, vamos escrever um pequeno programa que retorna um “Olá mundo”.

Vamos inicializar um novo módulo com o comando go mod init github.com/aprendagolang/live-reload e criar um arquivo main.go com o seguinte conteúdo.

package main

import (
    "net/http"

    "github.com/go-chi/chi/v5"
)

func main() {
    r := chi.NewRouter()

    r.Get("/", func(rw http.ResponseWriter, r *http.Request) {
        rw.Write([]byte("Olá Mundo"))
    })

     http.ListenAndServe(":8080", r)
}

Como estamos utilizando uma dependência externa, vamos executar o go mod tidy para atualizar nosso go.mod, que deve ficar parecido com isso:

module github.com/aprendagolang/live-reload

go 1.18

require github.com/go-chi/chi/v5 v5.0.7

Com nosso pequeno programa escrito, vamos instalar o Air.

Por ser escrito em Go, podemos fazer sua instalação utilizando o próprio install do Go.

go install github.com/cosmtrek/[email protected]

Para testar se deu tudo certo com a instalação, execute um air -v no seu terminal. Se a instação ocorreu sem problemas, você deverá ver o seguinte output:

Agora vamos criar um arquivo de configuração para o Air com o comando air init. Esse comando irá criar um arquivo chamado .air.toml com o seguinte conteúdo.

root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
  args_bin = []
  bin = "./tmp/main"
  cmd = "go build -o ./tmp/main ."
  delay = 1000
  exclude_dir = ["assets", "tmp", "vendor", "testdata"]
  exclude_file = []
  exclude_regex = ["_test.go"]
  exclude_unchanged = false
  follow_symlink = false
  full_bin = ""
  include_dir = []
  include_ext = ["go", "tpl", "tmpl", "html"]
  kill_delay = "0s"
  log = "build-errors.log"
  send_interrupt = false
  stop_on_error = true

[color]
  app = ""
  build = "yellow"
  main = "magenta"
  runner = "green"
  watcher = "cyan"

[log]
  time = false

[misc]
  clean_on_exit = false

[screen]
  clear_on_rebuild = false

Uma pequena mudança que eu gosto de fazer é mudar o time para true. Porém se você não quiser, não precisa alterar nada nesse arquivo.

Agora tudo que precisamos fazer é executar o comando air no terminal e nosso live reload já estará funcionando.

Para testar o live reload, vamos modificar o nosso r.Get("/", ... para o seguinte:

r.Get("/{name}", func(rw http.ResponseWriter, r *http.Request) {
    name := chi.URLParam(r, "name")

    rw.Header().Add("Content-Type", "application/json")
    json.NewEncoder(rw).Encode(map[string]string{
        "message": fmt.Sprintf("Olá %s!!!", name),
    })
})

Como podemos ver no terminal, a aplicação foi recompilada automaticamente.

É isso, espero que essa dica ajude a melhorar sua produtividade.

Deixem suas dúvidas nos comentários.

Até a próxima!


Subscreva

Fique por dentro de tudo o que acontece no mundo Go.

Como executar migrations de forma automatizada

Se você não é muito fã de ORMs como eu, um dos problemas que você mais enfrenta é o de como realizar alterações em seu banco de dados de forma segura e automática.

Nesse post, vou mostrar como fazer isso utilizando o Migrate (https://github.com/golang-migrate/migrate), um projeto open source escrito em Go para realizar migrations em bancos de dados.

Antes de começar, embora os exemplos contidos nesse tutorial serem utilizando postgres, o Migrate suporta os seguintes bancos de dados:

mongodb+srv, firebirdsql, clickhouse, cockroachdb, mongodb, mysql, sqlserver, cassandra, crdb-postgres, postgres, postgresql, spanner, stub, cockroach, neo4j, pgx, redshift, firebird.

Tendo esclarecido esse ponto, vamos iniciar um projeto com nome github.com/aprendagolang/migrate (go mod init github.com/aprendagolang/migrate) e depois escrever uma pequena API.

Leia mais »

Entenda o que são os arquivos go.mod e go.sum

Se você já trabalhou ou conhece um pouco de outras linguagens, podemos comprar o arquivo go.mod ao package.json do JS, composer.json do PHP ou requirements.txt do Python.

Ou seja, o arquivo go.mod, nada mais é do que o arquivo onde o Go vai gerenciar a lista de pacotes que sua aplicação precisa para funcionar.

Além das dependências, é nesse arquivo onde o Go adiciona o nome do seu package e a versão do Go que estava sendo utilizada no momento da criação do projeto.

Essa segunda informação é muito valiosa, pois com base nela o Go vai saber quais versões das dependências externas ele pode ou não utilizar.

Leia mais »

Como trabalhar com herança em Go

Uma dúvida que tenho visto com certa frequência é sobre as classes e herança em Go.

Sempre lembrando que GO não tem orientação a objetos na sua forma original de ser. Porém, quando o assunto é classe e herança, é possível alcançar algo similar utilizando structs e a técnica de embedding.

Tento esclarecido isso, vamos ver como podemos utilizar “herança” em Go imaginando um banco de dados com 4 tabelas.

imagem meramente ilustrativa 😉
Leia mais »

Como conectar e fazer CRUD em um banco PostgreSQL

Quando desenvolvemos programas que vão trabalhar com dados, sem sombra de dúvida uma das coisas mais importantes é armazenar esses dados com segurança e robustez.

Nesse post, vou mostrar como conectar e executar um CRUD utilizando um banco de dados PostgreSQL.

Antes de começar a escrever código, vamos fazer download do drive do postgres para Go com o comando go get github.com/lib/pq.

Ok, agora podemos começar.

Para ficar um pouco mais próximo da realidade, vou separar todas as operações em funções, incluindo a conexão com o banco.

Leia mais »

Como fazer encadeamento de métodos (chaining)

Chaining de métodos é uma técnica muito utilizada em linguagens como PHP, Java e C#. Se você não está familiarizado com o termo, não se preocupe, pois essa é uma técnica muito simples. Ela consiste em retornar um objeto para que outro método possa ser chamado sem a necessidade de atribuição a uma outra variável.

Essa técnica é muito utilizada em ORMs como o GORM, para construção de queries mais complexas.

No vídeo que postamos no nosso canal do youtube mostrando como construir uma API completa com go-chi e postgres (link para o vídeo), também podemos ver essa técnica sendo utilizada para fazer o decode da request para uma struct.

Para entender melhor seu funcionamento, vamos criar uma struct com 100% de seus atributos privados.

Leia mais »

Como utilizar go-chi para rotas e middleware

Durante muito tempo, gorilla/mux era o meu router favorito na hora de escrever APIs. Porém, desde que fiz o post sobre benchmark comparando gorilla/mux e go-chi (link para o post), meu router favorito tem sido o go-chi, pois sua performance é bem superior. E para ajudar, recentemente o projeto do gorilla/mux ficou sem mantenedor. ☹️

Por isso, resolvi fazer esse post para mostrar tudo o que você pode fazer com go-chi.

Para começar, vamos escrever um código muito simples para criar uma rota com o verbo GET.

Leia mais »

Como utilizar go workspaces

Dando continuidade aos posts onde exploramos as novas funcionalidades do Go 1.18, nesse post vamos ver como utilizar o novo Go Workspaces.

Para começar, vamos criar uma pasta e chama-lá de workspace.

Pequena observação antes de continuar, o nome dessa pasta NÃO tem que ser obrigatoriamente workspace, só coloquei esse nome por achar conveniente.

Agora, dentro da pasta workspace, vamos adicionar uma pasta chamada hello. Nessa pasta vamos colocar o nosso programa.

Dentro da pasta hello, vamos iniciar um novo módulo com o comando go mod init github.com/aprendagolang/hello e adicionar um arquivo main.go com o seguinte conteúdo.

Leia mais »

Trabalhando com datas

Acho que um dos assuntos que mais causa confusão, depois talvez de goroutines e channels, é a manipulação de datas em Go.

Nesse post vou mostrar como manipular, comparar, formatar e fazer parse de datas em Go.

Para iniciar, vamos “printar” a data atual da forma mais simples possível.

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    fmt.Println(now)
}
Leia mais »

Como utilizar generics em structs

A partir da versão 1.18 do Go, FINALMENTE temos o generics disponível para utilização. Em outros posts, que vou deixar aqui em baixo, já abordamos como utilizar generics em funções, como utilizar a contraint comparable e fizemos um pequeno benchmark para ver a diferença com funções comuns.

Essa semana enquanto fuçava no código fonte do Go, descobri que também podemos utilizar essa maravilha em structs.

Para demonstrar como utiliza-lo, vamos criar uma struct para fazer cache das structs PessoaFisica e PessoaJuridica.

Leia mais »