squirrel eating cone in forest

Como fazer fuzz test em requests HTTP (parte 1)

Na edição de 2022 da GopherCon Brasil, tive o prazer de palestrar sobre Fuzz Test. Foi muito bacana, pois durante a palestra, assim como nos corredores do evento, fizeram vários questionamentos que eu ainda não tinha feito sobre essa feature do Go.

Se você ainda não conhece esse tipo de teste, convido você a ler um post que publicamos aqui no blog (link para o post) onde explicamos melhor o assunto.

O que vou tratar nesse post é o resultado das perguntas feitas no evento mais um link que o Ricardo Maricato me enviou.

Para ver uma das formas de implementar o Fuzz Test para requests HTTP, vamos implementar um endpoint para validação dos dados de uma pessoa.

Vamos começar criando uma struct com um método de validação, e algumas variáveis para armazenar os erros de validação que podemos ter.

Leia mais »
business cargo cargo container city

Como fazer uma imagem Docker com multi stage build

Estando todos vivendo numa era onde computação em nuvem vem sendo cada vez mais adotada, saber trabalhar com containers acaba se torna praticamente uma obrigação.

Por isso, nesse post, vamos ver como criar uma imagem Docker otimizada com multi stage build para aplicações escritas em Golang.

Antes de começar escrever nosso Dockerfile, vamos criar um arquivo main.go e escrever uma pequena API para retornar o famoso “Olá Mundo”.

package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(rw, "Olá Mundo\\n")
	})

	log.Fatal(http.ListenAndServe(":8000", nil))
}
Leia mais »
two white printer papers near macbook on brown surface

Como ler e escrever arquivo CSV

Quando não temos uma API para realizar integrações, acredito que a utilização de um arquivo CSV para exportar ou importar dados, seja uma das formas mais utilizadas no planeta.

Por isso, se você ainda não se deparou com essa situação, com certeza em algum momento você irá.

Sem mais delongas, bora implementar um pequeno programa para ler um arquivo rh.csv que contém os seguintes dados.

Tiago Temporin,000.000.000-00,32
Maria Costa,111.111.111-11,27
João Augusto,333.333.333-33,22
Marta Leonel,444.444.444-44,40
Leia mais »
body of water between green leaf trees

Como fazer teste unitário no GORM com testify e sqlmock

No último final de semana, eu passei praticamente a tarde toda do domingo tentando escrever testes unitários para o GORM utilizando sqlmock.

O problema é que todos os tutoriais que eu encontrei eram de versões antigas, tanto do GORM, quanto do sqlmock.

Somente na segunda-feira, depois de mais umas 2h tentando entender como eles funcionavam e o que os erros estavam me dizendo foi que consegui fazer os testes funcionarem.

Por causa desse trabalho todo, resolvi fazer esse post mostrando como escrever testes unitários para GORM com sqlmock e testify.

Se você nunca utilizou testify ou quer saber um pouco mais sobre, recomendo a leitura do nosso post “Como usar testify para escrever testes“. Além de um exemplo básico, explicamos qual a finalidade de cada um dos 4 packages que compõem a suite do testify.

Continuando… para facilitar, vou separar o post em testes para INSERT, UPDATE, DELETE e SELECT.

Leia mais »
hanging decor lot

O que são e como utilizar tags em structs

Uma feature pouco comentada porém muito útil na linguagem Go, pelo menos no meu ponto de vista, é a tag.

As tags são marcações que colocamos nas propriedades de uma struct. Essas marcações funcionam como metadata para outros packages poderem realizar operações.

Para ficar mais claro, vamos criar um struct comum.

type Pessoa struct {
  Nome      string
  Documento string
  Idade     uint8
}
Leia mais »
red and yellow hatchback axa crash tests

Como usar testify para escrever testes

Se você ainda não conhece, Testify é um conjunto de ferramentas para nos auxiliar na hora de escrever testes e mocks.

Por ser uma “casquinha” feita em cima dos próprios testes do Go, a utilização desse package não deve causar grandes problemas.

Na data em que escrevo esse post, o Testify é dividido em 4 packages:

Para começar, considerando o código abaixo, vamos ver como o package assert pode nos ajudar.

Leia mais »
depth of field photography of file arrangement

Como listar arquivos de um diretório

Nesse post vou mostrar três formas diferentes para ler um diretório com Golang.

[SPOILER ALERT] No final desse post vou mostrar como eu apliquei um dos exemplos para poder ler um diretório que continha mais de 3.6 milhões de arquivos.

Vamos iniciar os exemplos utilizando a função ReadDir do package ioutil.

package main

import (
    "fmt"
    "io/ioutil"
    "log"
)

func main() {
    files, err := ioutil.ReadDir("/tmp/")
    if err != nil {
        log.Fatal(err)
    }

    for _, file := range files {
        fmt.Println(file.Name(), file.IsDir())
    }
}
Leia mais »
gray concrete road near forest

Mutex ou channels? Como resolver race condition

Existem basicamente duas formas para resolver problemas de race condition. Mutex e Channels.

Se você não está familiarizado com o termo race condition, não se preocupe. Esse termo é utilizado para descrever um pedaço do código que será executado por múltiplas goroutines e que, a cada execução, seu resultado pode variar devido a forma como o Go alterna a execução entre goroutines.

Para ficar um pouco mais claro, vamos dar uma olhada no código abaixo.

package main

import (
	"fmt"
	"sync"
)

var total = 0

func count(wg *sync.WaitGroup) {
	total++
	wg.Done()
}

func main() {
	var wg sync.WaitGroup

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go count(&wg)
	}
	wg.Wait()
	fmt.Println("total: ", total)
}
Leia mais »

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/air@latest

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!


Faça parte da comunidade!

Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.

* indicates required

Livros Recomendados

Abaixo listei alguns dos melhores livros que já li sobre 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 »