DEV Community

Cover image for Começando com Go - parte 1 - O início
Marcelo Pinheiro
Marcelo Pinheiro

Posted on

Começando com Go - parte 1 - O início

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.

mkdir -p communication-engine/management_api
Enter fullscreen mode Exit fullscreen mode

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.

cd communication-engine/management_api
mkdir api
mkdir config
Enter fullscreen mode Exit fullscreen mode

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

package config

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

Enter fullscreen mode Exit fullscreen mode

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:

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())
    }
}
Enter fullscreen mode Exit fullscreen mode

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?

go run management_api/api/main.go
Enter fullscreen mode Exit fullscreen mode

Se tudo está certo, você deve estar vendo o seguinte output na sua tela:

2021/03/16 09:55:57 Listening on port 8080
Enter fullscreen mode Exit fullscreen mode

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

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á!

Top comments (0)