10 - Criando o Modelo de Dados (Struct) e Armazenamento

Agora que já sabemos como gerar identificadores robustos e responder em JSON, chegou o momento de darmos um passo crucial na nossa API: criar o nosso modelo de dados e preparar o local onde guardaremos as informações de vários estudantes simultaneamente.

O que é uma Struct no Go?

O Go não possui classes como outras linguagens orientadas a objetos (Java, C#, PHP). Em vez disso, nós agrupamos propriedades de tipos diferentes utilizando uma Struct (Estrutura). Ela funciona como um molde ou um modelo que define todas as características que um determinado objeto do nosso sistema deve ter.

A Regra de Ouro: Letras Maiúsculas e Exportação

Antes de olharmos o código, preste muita atenção em um detalhe que costuma confundir quem está começando em Go: a primeira letra do nome de cada propriedade DEVE ser maiúscula.

No Go, a visibilidade de uma propriedade ou função é definida pelo seu nome:

  • Letra inicial minúscula: A propriedade fica privada (visível apenas dentro daquele pacote).
  • Letra inicial maiúscula: A propriedade fica pública (exportada para outros pacotes).

Como o pacote externo de conversão de dados do Go (encoding/json) precisa ler o nosso modelo para transformá-lo em texto JSON, se deixarmos as propriedades com letra minúscula, o Go vai escondê-las, e a sua API vai retornar um objeto JSON completamente vazio!

Passo 1: Definindo a nossa Struct Aluno

Para o nosso projeto, vamos adicionar o modelo logo acima da função helloWorld. Além de definir as variáveis com letras maiúsculas, usaremos os chamados JSON Tags (os textos entre crases) para dizer ao Go como o nome desse campo deve aparecer escrito no nosso JSON final (em letras minúsculas). Veja como fica a estrutura:

// Modelo (Struct) que define os dados de um estudante
// Note a primeira letra maiúscula para exportar os campos para o pacote JSON
type Aluno struct {
	Codigo   string  `json:"codigo"`
	Nome     string  `json:"nome"`
	Nota1    float64 `json:"nota1"`
	Nota2    float64 `json:"nota2"`
	Media    float64 `json:"media"`
	Situacao string  `json:"situacao"`
}

Passo 2: O Banco de Dados em Memória (Slices)

Uma API precisa guardar as informações que recebe. Como ainda não estamos conectados a um banco de dados real (como MySQL ou PostgreSQL), usaremos uma estrutura de dados nativa do Go chamada Slice (fatia).

O Slice funciona como uma lista ou array dinâmico, que pode crescer ou diminuir de tamanho automaticamente. Vamos criar uma variável global chamada alunos que será responsável por armazenar a nossa lista de estudantes do tipo Aluno:

// Slice (lista dinâmica) que servirá como nosso banco de dados temporário em memória
var alunos = []Aluno{}

Passo 3: Integrando Tudo ao Arquivo main.go

Vamos juntar a Struct e a nossa nova lista global dentro do código. Por enquanto, criaremos um aluno de teste, vamos adicioná-lo à nossa lista de alunos e retornar essa lista inteira no formato JSON. Atualize o seu arquivo com o código completo abaixo:

// Pacote principal da aplicação
package main

// Importações
import (
	"encoding/json"
	"fmt"
	"net/http"

	"://github.com"
)

// Nosso Modelo de Dados
type Aluno struct {
	Codigo   string  `json:"codigo"`
	Nome     string  `json:"nome"`
	Nota1    float64 `json:"nota1"`
	Nota2    float64 `json:"nota2"`
	Media    float64 `json:"media"`
	Situacao string  `json:"situacao"`
}

// Slice global que funciona como nosso banco de dados em memória
var alunos = []Aluno{}

// Função para retornar a lista de alunos
func helloWorld(w http.ResponseWriter, r *http.Request) {

	// 1. Definir o cabeçalho como JSON
	w.Header().Set("Content-Type", "application/json")

	// 2. Definir o Status Code 201
	w.WriteHeader(http.StatusCreated)

	// 3. Criar e preencher uma instância do nosso modelo Aluno
	alunoTeste := Aluno{
		Codigo:   uuid.New().String(),
		Nome:     "Ronaldo Lima",
		Nota1:    8.5,
		Nota2:    7.5,
		Media:    8.0,
		Situacao: "Aprovado",
	}

	// 4. Limpar a lista e adicionar o aluno de teste dentro do nosso slice (banco de dados)
	// Usamos o append para empurrar o objeto para dentro da lista
	alunos = []Aluno{alunoTeste}

	// 5. Converter a lista completa de alunos para JSON e retornar
	json.NewEncoder(w).Encode(alunos)
}

// Função principal
func main() {

	// Rotas
	http.HandleFunc("GET /", helloWorld)

	// Retornar o funcionamento do servidor
	fmt.Println("Servidor em execução no endereço: http://localhost:8080")

	// Configurar servidor
	http.ListenAndServe(":8080", nil)

}

Passo 4: Visualizando o modelo em ação

Abra seu navegador e acesse http://localhost:8080. O resultado agora trará colchetes [ ] envolvendo o objeto, o que indica que a sua API está retornando uma lista estruturada (Array/Slice) de alunos com sucesso:

[
  {
    "codigo": "7e3b1458-ba81-4231-9012-abcde9876543",
    "nome": "Ronaldo Lima",
    "nota1": 8.5,
    "nota2": 7.5,
    "media": 8,
    "situacao": "Aprovado"
  }
]