Começando com Go - parte 1 - O início 
Published: 2021-03-16 10:01:32


Salve, meu povo, tudo certo? Espero que sim.

Bom, eu resolvi começar a aprender Golang, a linguagem para backend criada pelo Google. Não vou entrar em detalhes do que é a linguagem ou do porquê de eu decidir começar a aprendê-la. Tem materiais por aí muito melhor escritos do que qualquer coisa que eu pudesse colocar aqui. A intenção desta série é ir acompanhando e documentando meu desenvolvimento e descobertas e quem sabe, servir para alguém que estiver nessa mesma jornada.

## O que vou construir?

Uma plataforma SaaS multitenancy que se integra a varias formas de envio de mensagem (E-mail, SMS, Voz, qualquer jeito que exista de se comunicar com um cliente) e, de forma escalável centralize estes envios, através de um api. Também teremos um portal em que seja possível administrar os meus envios, clientes, aplicações que poderão utilizar a api da ferramenta, etc.

Tenho algumas premissas para esta construção:
- Implementação de uma base de dados (Postgres) com migrações
- Implementação de uma mensageria (Rabbitmq) para gerenciar as solicitações de envio vindos da API.
- Arquitetura escalável (microsserviços)
- Docker
- API Rest documentada com Swagger
- Clean Architecture
- Monorepo
- Coverage de testes unitários acima de 80%

O resto, vamos ajustando durante essa jornada. Bora lá?

## Antes: instale o go
Não é o propósito desta postagem explicar a instalação, tampouco como iniciar um projeto (dependencias, etc). A documentação é bem completa, da uma passada lá :D (btw, o link é: https://golang.org/)

No entanto, uma coisa que está me ajudando muito é utilizar as extensões de golang do vscode. Poupei bastante tempo com a questão das dependências do projeto.

## Começando: estruturação
Sempre tive uma ótima experiência com clean architecture quando o assunto é organização do projeto. O software cresce de forma orgânica, fácil de ler e documentada. Como não vou inventar a roda, vou basear toda a minha estrutura do projeto no repositório https://github.com/eminetto/clean-architecture-go-v2 (Obrigado, eminetto). Achei a estrutura simples yet completa, me parece ser um bom início.

## Então, começando:
A primeira coisa que fiz foi criar um diretório chamado `communication-engine`, que vai ser a raiz do meu projeto e dentro dele, um diretório `management_api`, que vai ser o diretório que vai guardar a minha api responsável por servir, futuramente, a aplicação front-end.
```bash
mkdir -p communication-engine/management_api
```

Dentro da pasta `management_api`, eu criei dos diretórios, o `api`, que vai guardar todos os meus arquivos relacionados a api (handlers, middlewares, modelos de apresentação, etc) e também a pasta `config`, cujo propósito é autodescritivo. 
```bash
cd communication-engine/management_api
mkdir api
mkdir config
```

Na pasta `config`, eu criei o arquivo `config_dev.go`, com o seguinte conteúdo
```go
package config

const (
	DB_USER     = "communication_engine"
	DB_PASSWORD = "communication_engine"
	DB_DATABASE = "communication_engine"
	DB_HOST     = "127.0.0.1"
	API_PORT    = 8080
)

```

Já na pasta `api`, o primeiro arquivo que criei foi o `main.go`, que vai ser o arquivo de entrada da nossa api. A implementação dele, por enquanto, é bem simples:
```go
package main

import (
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/gorilla/context"
	"github.com/gorilla/mux"
	"github.com/marcelocpinheiro/communication-engine/management_api/config"
)

func main() {
    //Instância um novo roteador MUX, um roteador http para go
	r := mux.NewRouter()

    // Repassa as rotas para o roteador
	http.Handle("/", r)

    // Cria um handler para a url "/ping", escreve "running" na tela e retorna o status 200
	r.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
		io.WriteString(w, "Running")
		w.WriteHeader(http.StatusOK)
	})

    // Cria um logger para a aplicação
	logger := log.New(os.Stderr, "logger: ", log.Lshortfile)

    // Instancia um novo servidor com configurações específicas de timeout, endereço, log e handler
	srv := &http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
		Addr:         ":" + strconv.Itoa(config.API_PORT),
		Handler:      context.ClearHandler(http.DefaultServeMux),
		ErrorLog:     logger,
	}

    //Printa na tela a porta que a aplicação está ouvindo
	log.Printf("Listening on port %d", config.API_PORT)

   //inicia o servidor e, se houver erro, mata a aplicação e printa o erro
	err := srv.ListenAndServe()
	if err != nil {
		log.Fatal(err.Error())
	}
}
```
**Importante**: A importação da config se você estiver replicando esse projeto vai ser de acordo com o endereço de repositório que você especificou para o seu projeto, o que obviamente vai ser diferente do meu (espero). 

Vamos ver se isso está funcionando?


```bash
go run management_api/api/main.go
```

Se tudo está certo, você deve estar vendo o seguinte output na sua tela: 
```bash
2021/03/16 09:55:57 Listening on port 8080
```

E aí, o que resta é abrir o seu browser e bater na url `http://localhost:8080/ping`. Você deve ver a palavra "Running" na tela. É isso, criamos o primeiro endpoint. 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcshyu8xrxqo5x417mio.png)
 

Fique ligado para acompanhar a série, e siga @devmediano no instagram, devo estar postando mais sobre essa série por lá.

No próximo post vamos criar o primeiro endpoint dentro da estrutura do router, e já responder requisições post dentro da estrutura do clean architecture que está sendo utilizada. Até lá!