Pular para o conteúdo principal

victorstein.dev

63/100 Dias de Golang - Gerando dados com Faker

# Gerando dados com Faker

Para não testarmos os dados sempre com o John Doe, temos a lib Faker ela permite gerar dados aleatórios para várias situações: nomes, endereços, números, textos e vários outros dados. Podemos usar isso em testes automatizados, mocks, geração de dados para popular um banco, …

Para instalar a lib:

go get -u github.com/go-faker/faker/v4

Vamos criar um script que define uma struct de User e vamos gerar dados fake para esse user. Veja que usamos o padrão das struct tags para definir as condições para o Faker

Ler Mais

62/100 Dias de Golang - Testes - Mockgen

# Testes - Mockgen

Vamos usar a lib gomock para gerar os mocks.

Vamos criar um projeto e instalar a lib:

go install go.uber.org/mock/mockgen@latest

Agora basta criar o nosso service/user_service.go.

package service

type UserService interface {
    GetUser(id int) (string, error)
    CreateUser(name string) error
}

E agora o comando mágico para gerar os mocks:

mockgen -source=./service/user_service.go -destination=./mocks/mock_user_service.go -package=mocks

Vai ser criado um arquivo mocks/mock_user_service.go

// Code generated by MockGen. DO NOT EDIT.
// Source: ./service/user_service.go
//
// Generated by this command:
//
//	mockgen -source=./service/user_service.go -destination=./mocks/mock_user_service.go -package=mocks
//

// Package mocks is a generated GoMock package.
package mocks

import (
	reflect "reflect"

	gomock "go.uber.org/mock/gomock"
)

// MockUserService is a mock of UserService interface.
type MockUserService struct {
	ctrl     *gomock.Controller
	recorder *MockUserServiceMockRecorder
	isgomock struct{}
}

// MockUserServiceMockRecorder is the mock recorder for MockUserService.
type MockUserServiceMockRecorder struct {
	mock *MockUserService
}

// NewMockUserService creates a new mock instance.
func NewMockUserService(ctrl *gomock.Controller) *MockUserService {
	mock := &MockUserService{ctrl: ctrl}
	mock.recorder = &MockUserServiceMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockUserService) EXPECT() *MockUserServiceMockRecorder {
	return m.recorder
}

// CreateUser mocks base method.
func (m *MockUserService) CreateUser(name string) error {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "CreateUser", name)
	ret0, _ := ret[0].(error)
	return ret0
}

// CreateUser indicates an expected call of CreateUser.
func (mr *MockUserServiceMockRecorder) CreateUser(name any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockUserService)(nil).CreateUser), name)
}

// GetUser mocks base method.
func (m *MockUserService) GetUser(id int) (string, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetUser", id)
	ret0, _ := ret[0].(string)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// GetUser indicates an expected call of GetUser.
func (mr *MockUserServiceMockRecorder) GetUser(id any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUser", reflect.TypeOf((*MockUserService)(nil).GetUser), id)
}

E depois basta escrever o teste para com o mock. Aqui a diferença vai ser a forma com que moldamos o comportamento do mock em relação ao testify. Veja a função mockUserService.EXPECT()

Ler Mais

61/100 Dias de Golang - Testes - Mocks

# Testes - Mocks

Já escrevi algumas vezes sobre testes aqui no blog:

Mas está faltando falar sobre Mocks. Mocks são estruturas que simulam o comportamento de componentes externos (como bancos de dados, APIs, …) para testar a lógica de negócio sem depender desses serviços. Em Go podemos fazer isso de diversas formas. Uma delas é utilizando a biblioteca testify.

Ler Mais

60/100 Dias de Golang - Jogo em UDP - Parte 6

# Jogo em UDP - Parte 6

Para fechar o jogo, vamos criar um objetivo. Qual player chegar primeiro na coordenada X, Y vence. O que vamos ter que alterar: fazer uma verificação se algum player está na posição de vitória, enviar uma mensagem de vitória depois que alguém alcançar a posição e travar a movimentação dos players após a vitória.

Vamos primeiro adicionar nossas variáveis:

var goalPosition = [2]int{arenaRows - 2, arenaCols - 2}
var gameOver = false
var winner string

Vamos adicionar uma verificação, caso gameOver seja verdade, não enviamos mais os comando para o canal

Ler Mais

59/100 Dias de Golang - Jogo em UDP - Parte 5

# Jogo em UDP - Parte 5

Hoje vamos corrigir um problema no jogo e mostrar o código completo. Como várias goroutines acessam a lista de players ou um player específico temos que usar um Mutex para não termos race condition. Vamos começar criando o mutex.

var players = make(map[string]*Player)
var playersMutex sync.Mutex

E sempre que acessarmos essa variável, temos que dar um Lock e Unlock nela. Vou colocar somente um exemplo aqui:

Ler Mais

58/100 Dias de Golang - Jogo em UDP - Parte 4

# Jogo em UDP - Parte 4

Hoje vamos implementar a função que processa os comandos recebidos no servidor e atualiza o grid com a posição dos jogadores. Essa função que processa os comandos do grid vai ser uma goroutine que fica escutando o canal commands. Ela vai receber a struct Command, que possui o ID do jogador e qual o comando.

type Command struct {
	PlayerID string
	Action   string
}

Vamos implementar nela também alguma verificações da posição do jogador no grid, ele não pode ficar em posições negativas nem na borda do grid. Para cima e para baixo verificamos se a posição é maior que 0 e menor que o número de linhas e para a esquerda e para a direita. E verificamos também se a posição é uma borda.

Ler Mais

57/100 Dias de Golang - Jogo em UDP - Parte 3

# Jogo em UDP - Parte 3

Hoje iremos enviar o grid para cada usuário conectado e receber os inputs de cada usuário. Já temos a função renderArene que retorna uma string formatada e já temos a lista de playes, o que vamos criar é uma função envia a arena para todos os usuário. Mais o menos nessa estrutura.

arena := renderArena()
sendArena(conn, arena)

A função sendArena vai fazer um for sobre a lista de usuários e enviar para cada usuário o grid no endereço salvo.

Ler Mais

56/100 Dias de Golang - Jogo em UDP - Parte 2

# Jogo em UDP - Parte 2

Nesse post focaremos em fazer algumas funções do server. Como criar as conexões inicias, salvar usuários, ver quais informações precisamos salvar de cada usuário e criar o grid.

Para iniciar o servidor UDP, muito simples. Já vimos isso em outro post também.

addr, _ := net.ResolveUDPAddr("udp", "0.0.0.0:8080")
conn, _ := net.ListenUDP("udp", addr)
defer conn.Close()

fmt.Println("Servidor iniciado na porta 8080...")

De modo geral, estou imaginando a função main com 3 rotinas principais:

Ler Mais

55/100 Dias de Golang - Jogo em UDP - Parte 1

# Jogo em UDP

Vamos criar um jogo no terminal, usando o protocolo UDP. para comunicação entre o client e o server. O jogo será baseado em um grid, onde o jogador poderá se movimentar livremente, o objetivo do jogo é chegar com o “personagem” em uma determinada coordenada do grid. O jogo suportará múltiplos jogadores e será executado diretamente no terminal. A cara dele vai ser mais ou menos essa:

Ler Mais

54/100 Dias de Golang - Sockets em UDP

# Sockets em UDP

No post passado fizemos uma aplicação usando o Melody, que serve para facilitar o uso de Websockets. O websocket é um protocolo que está sobre o HTTP e o HTTP roda sobre o TCP. Vamos ver aqui uma implementação de sockets usando UDP, não confunda o Socket com Websocket. Websocket é o protocolo e socket é uma interface de comunicação. E hoje faremos um socket UDP. O UDP (User Datagram Protocol) é ideal para aplicações que priorizam velocidade sobre confiabilidade. UDP é um protocolo sem conexão que não garante entrega de pacotes, não mantém orde de mensagens e possui baixo overhead em relação ao TCP. Em Go, trabalhar com UDP é simples pois podemos usar a lib padrão net. Veja a implementação de um server:

Ler Mais