Pular para o conteúdo principal

victorstein.dev

27/100 Dias de Golang - Testes de benchmark

# Benchmarking em Go: Medindo e Otimizando o desempenho

Como você deve ter visto até aqui, testes em go são muito simples e a biblioteca padrão nos oferece recursos bem poderosos. Outra ferramenta que a biblioteca testing oferece de forma nativa é o benchmarking. O benchmarking serve para diversas finalidades, todas relacionadas à avaliação e otimização do desempenho de sistemas, aplicações, algoritmos ou componentes de software. A questão mais legal que eu achei foi a comparação de implementações, testar qual implementação de uma função performa melhor que outra. Veja como é simples fazer esses testes:

Ler Mais

26/100 Dias de Golang - Testes em batch, AAA e Cobertura de Código

# Testes em batch

Vamos adicionar mais alguns testes na função de soma, agora vamos testar com dois valores negativos, com somente um valor negativo e com zero.

func TestSomaTwoNegatives(t *testing.T) {
	total := Soma(-5, -10)

	expected := -15

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

func TestSomaOneNegative(t *testing.T) {
	total := Soma(5, -10)

	expected := -5

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

func TestSomaWithZero(t *testing.T) {
	total := Soma(5, 0)

	expected := 5

	if total != expected {
		t.Errorf("Esperava %d recebi %d", expected, total)
	}
}

O que você achou de todos esses testes? Não parece contraintuitivo gerar uma função para cada caso da função Soma? Só estamos trocando os parâmetros, parece desnecessário repetir toda a estrutura. Para resolver esse problema o Go possui o teste em batch. Veja como fazemos esse teste em batch.

Ler Mais

25/100 Dias de Golang - Testes em Golang

# Testes

Uma das coisas mais interessantes da linguagem é o suporte nativo a testes. Diferente de muitas linguagens que dependem de frameworks externos, o Go já vem pronto para testar! Testes automatizados evitam bugs, documentam o comportamento do código e facilitam refatorações. Esse post será bem introdutório, podemos explorar bem a fundo a questão dos testes, talvez criar um mini biblioteca para usarmos de exemplo.

# Pacote testing

Esse pacote padrão do Go oferece as ferramentas básicas para escrever testes unitários . Para começar vamos criar um arquivo chamado utils.go e colocar uma função bem simples de soma:

Ler Mais

24/100 Dias de Golang - Continuação sobre a biblioteca “time”

# Continuação sobre a biblioteca “time”

​No post “22/100 Dias de Golang - Biblioteca ’time’” , foram abordadas funcionalidades básicas da biblioteca time do Go, como obter o horário atual, acessar componentes individuais da data e formatar datas. Vamos aprofundar esses conceitos e explorar recursos mais avançados da biblioteca

# Fusos Horários

No Go, o pacote time permite converter entre fusos horários utilizando o tipo Location

Ler Mais

23/100 Dias de Golang - Manipulação de arquivos

# Manipulação de arquivos

Clássico conteúdo de manipulação de arquivos, como fazer a leitura, como escrever, como escreve com append, como ler linha a linha, como renomear um arquivo, como deletar… O famoso CRUD dos arquivos.

# Criar e escrever

Para criar um arquivo, vamos usar a função os.Create(nomeArquivo) da biblioteca padrão os.

nomeArquivo := "meu_arquivo.txt"

arquivo, err := os.Create(nomeArquivo)
if err != nil {
	panic(err)
}

Lembrar de sempre quando trabalhar com arquivos usar o defer. O defer atrasa a execução da função que o segue até que a função em que ele está seja concluída. No caso de arquivo.Close(), isso garante que o arquivo será fechado corretamente, independentemente de como a função termina. O mais legal é que isso é independente de como a função finaliza, seja com com um erro o de forma normal.

Ler Mais

22/100 Dias de Golang - Biblioteca “time”

# Biblioteca “time”

Já usamos em vários exemplos essa biblioteca, usando para o famose sleep. Agora vamos dar uma olhada mais a fundo nela. Já vamos começar com a mais clásica de todas, pegar o horário atual

package main

import (
	"fmt"
	"time"
)

func main() {

	now := time.Now()

	fmt.Println(now)
}

Se você executar esse programa, verá uma saída nesse format:

2025-04-03 21:31:41.020649931 -0300 -03 m=+0.000047023

Perceba que o timezone vem no fomato -0300 e no formato abreviado -03. O diferente é o retorno do m=+0.000047023. Esse campo aparece quando imprimimos diretamente um time.Time. Esse valor é conhecido como “monotonic clock reading”, ou tempo monotônico, e serve para ajudar o Go a fazer medições de tempo com alta precisão. m=+0.000058133 quer dizer que o Go registrou esse momento como sendo +58.133 microssegundos desde um ponto de referência interno. Ele serve para medir duração entre eventos, como timers, benchmarks, e medições de performance.

Ler Mais

21/100 Dias de Golang - JSON

# JSON

Vamos sair um pouco do assunto das goroutines e ir para uma coisa mais “tranquila”, vamos falar sobre JSON, especificamente no Golang. Vamos dar um exemplo inicial de como transformar uma struct em um JSON. Depois de 20 dias, estou mais acostumado com a sintaxe do Go, espero que você também esteja.

package main

import "encoding/json"

type Animal struct {
	NomeCientifico  string
	NomePopular     string
	Patas           int
	NaturalDoBrasil bool
}

func main() {

	caramelo := Animal{
		NomeCientifico:  "Caramelus Brasiliensis",
		NomePopular:     "Caramelo",
		Patas:           4,
		NaturalDoBrasil: true,
	}

	res, err := json.Marshal(caramelo)

	if err != nil {
		println(err)
	}

	println(res)

}

A parte nova desse programa é a parte da serialização da struc para JSON. Fazemos isso com a função res, err := json.Marshal(caramelo). A função json.Marshal retorna um ([]byte, error). Perceba que é retornado um slice de bytes, rodando esse programa temos a seguinte saída:

Ler Mais

20/100 Dias de Golang - Exemplo de goroutines, mutex e channels

# Resolvendo o problema do Starbucks

Vamos “resolver” o problema do Starbucks. Para quem não sabe do que estou falando: Problema de race condition no starbucks afeta gift cards. Vamos criar um programa bem simples para simular isso e já aproveitamos para treinar os conhecimentos até aqui. Então o que teremos: pessoas com saldo nas contas e uma função que você pode transferir saldo do gift card de uma conta para outra. Vou fazer o programa de forma evolucional, começando bem simples e incrementar aos poucos.

Ler Mais

19/100 Dias de Golang - Channels

# Channels

Os channels nos permitem segurança para comunicação entre as threads. Extraído do livro A Linguagem de Programação Go:

Um canal é um sistema de comunicação que permite a uma gorrotina enviar valores para outra gorrotina E como tudo é fortemente tipado no Go, cada canal possui um tipo, veja como é simples criar um channel:

ch := make(chan int)

Com canais podemos fazer duas operações, enviar e receber. Vamos fazer um exemplo bem simples. Criar uma goroutine que envia uma informação para um canal e vamos printar esse valor fora dessa goroutine

Ler Mais

18/100 Dias de Golang - Goroutines, WaitGroup, Race condition e Mutex

# Goroutines

Vamos continuar a nossa jornada com as goroutines. Quero fazer mais um exemplo aqui.

package main

import (
	"fmt"
	"time"
)

func task(name string, n int) {

	for i := 0; i < n; i++ {
		fmt.Printf("Task: %s, i:%d/%d\n", name, i, n)
		time.Sleep(500 * time.Millisecond)

	}
}

func main() {

	go task("1", 5)
	go task("2", 7)

	time.Sleep(10 * time.Second)

}

Veja a saída desse programa:

Task: 2, i:0/7
Task: 1, i:0/5
Task: 1, i:1/5
Task: 2, i:1/7
Task: 2, i:2/7
Task: 1, i:2/5
Task: 1, i:3/5
Task: 2, i:3/7
Task: 2, i:4/7
Task: 1, i:4/5
Task: 2, i:5/7
Task: 2, i:6/7

Talvez esse exemplo seja mais elucidativo do que o anterior. Nele podemos ver claramente as duas goroutines rodando. O mais legal disso tudo foi a simplicidade de criar uma goroutine. No python, por exemplo, você teria que usar o threading ou multiprocessing para fazer isso. Perceba que o time.Sleep(10 * time.Second) é só um recursso técnico não convencional gambiarra. Uma das formas de resolver isso é um WaitGroup.

Ler Mais