0% acharam este documento útil (0 voto)
2 visualizações12 páginas

Estruturação Avançada de Dados em Go

Enviado por

marlon rodrigues
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato TXT, PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
2 visualizações12 páginas

Estruturação Avançada de Dados em Go

Enviado por

marlon rodrigues
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato TXT, PDF, TXT ou leia on-line no Scribd

// ============================================

// GO AVANÇADO: ESTRUTURAÇÃO DE DADOS


// ============================================
// Guia completo sobre organização e estruturação
// eficiente de dados em Go, desde padrões básicos
// até estratégias avançadas de design

// ============================================
// SUMÁRIO COMPLETO
// ============================================
// PRINCÍPIOS FUNDAMENTAIS
// 1. Padrão Value vs Pointer
// 2. Composição sobre herança
// 3. Encapsulamento (maiúsculas/minúsculas)
// 4. Imutabilidade
// 5. Zero values
//
// PADRÕES DE AGREGAÇÃO
// 6. Embedded types
// 7. Composição de structs
// 8. Padrão Builder
// 9. Padrão Factory
// 10. Padrão Object Pool
//
// SERIALIZAÇÃO E METADADOS
// 11. Tags de struct
// 12. JSON marshaling/unmarshaling
// 13. Custom marshalers
// 14. Validação de dados
// 15. Conversão entre tipos
//
// PADRÕES AVANÇADOS
// 16. Functional Options Pattern
// 17. Configuration Objects
// 18. Data Transfer Objects (DTOs)
// 19. Value Objects
// 20. Padrões com generics (1.18+)

package main

import (
"encoding/json"
"fmt"
"log"
"strconv"
"strings"
)

// ============================================
// 1. PADRÃO VALUE VS POINTER
// ============================================

// Valor pequeno: use value receiver


// Strings, números pequenos, estruturas leves são ideais para valores
type Coordenada struct {
X, Y float64
}

// Value receiver é apropriado porque Coordenada é pequena


func (c Coordenada) Distancia() float64 {
return (c.X * c.X) + (c.Y * c.Y)
}

// Estrutura maior: use pointer receiver


// Quando precisa de mutação ou economizar memória em passagens de parâmetro
type Usuario struct {
ID int
Nome string
Email string
Telefone string
Endereco string
Dados []string // campo maior
}

// Pointer receiver para não copiar a estrutura inteira


func (u *Usuario) AtualizarEmail(novoEmail string) {
[Link] = novoEmail
}

func exemplo_value_vs_pointer() {
// Value: cópia completa, modificações não afetam original
c1 := Coordenada{3, 4}
c2 := c1 // cópia
// c2 é independente de c1

// Pointer: referência, modificações afetam original


u1 := &Usuario{ID: 1, Nome: "João", Email: "joao@[Link]"}
u2 := u1 // u2 aponta para o mesmo Usuario
[Link]("newemail@[Link]")
[Link]("Email u1:", [Link]) // também mudou!
}

// ============================================
// 2. COMPOSIÇÃO SOBRE HERANÇA
// ============================================

// Em Go não existe herança, apenas composição através de embedding


type Animal struct {
Nome string
Peso float64
}

func (a Animal) Fazer_Som() string {


return "Som genérico"
}

// Composição: Cachorro "contém" um Animal


type Cachorro struct {
Animal // Embedded - promove campos e métodos
Raca string
Treinado bool
}

// Podemos sobrescrever métodos


func (c Cachorro) Fazer_Som() string {
return "Au au!"
}
// Composição também funciona sem embedding
type Veiculo struct {
Marca string
Modelo string
}

type Carro struct {


Veiculo // embedded
NumPortas int
Combustivel string
}

func exemplo_composicao() {
// Cachorro promove campos de Animal
dog := Cachorro{
Animal: Animal{Nome: "Rex", Peso: 30},
Raca: "Labrador",
Treinado: true,
}

[Link]("Nome:", [Link]) // acesso promovido


[Link]("Som:", dog.Fazer_Som())

// Acesso explícito também funciona


[Link]("Som via Animal:", [Link].Fazer_Som())

// Carro herda método de Veiculo (se houver)


carro := Carro{
Veiculo: Veiculo{Marca: "Toyota", Modelo: "Corolla"},
NumPortas: 4,
Combustivel: "Gasolina",
}
[Link]("Marca:", [Link]) // promovido
}

// ============================================
// 3. ENCAPSULAMENTO (MAIÚSCULAS/MINÚSCULAS)
// ============================================

// Campos públicos (maiúsculas) são visíveis fora do pacote


type ContaBancaria struct {
Titular string // público
Saldo float64 // público

// Campos privados (minúsculas) são visíveis apenas dentro do pacote


dataAbertura string
taxaJuros float64
transacoes []string
}

// Getter privado (convenção)


func (c *ContaBancaria) obter_taxa_juros() float64 {
return [Link]
}

// Setter público com lógica de validação


func (c *ContaBancaria) Definir_Taxa_Juros(taxa float64) error {
if taxa < 0 || taxa > 0.5 {
return [Link]("taxa deve estar entre 0 e 0.5, recebido: %v", taxa)
}
[Link] = taxa
return nil
}

// Método público que usa dados privados


func (c *ContaBancaria) Calcular_Juros(meses int) float64 {
return [Link] * [Link] * float64(meses) / 12
}

func exemplo_encapsulamento() {
conta := &ContaBancaria{
Titular: "Maria",
Saldo: 1000,
dataAbertura: "2024-01-01",
taxaJuros: 0.05,
}

[Link]("Titular:", [Link])
[Link]("Juros em 6 meses:", conta.Calcular_Juros(6))

// Não podemos acessar dataAbertura diretamente fora do pacote


// [Link]([Link]) // erro de compilação

// Usar método público


err := conta.Definir_Taxa_Juros(0.08)
if err != nil {
[Link]("Erro:", err)
}
}

// ============================================
// 4. IMUTABILIDADE
// ============================================

// Struct imutável: campos privados, sem setters


type DataImuvel struct {
dia int
mes int
ano int
}

// Construtor que valida


func Nova_Data(dia, mes, ano int) (*DataImuvel, error) {
if dia < 1 || dia > 31 || mes < 1 || mes > 12 {
return nil, [Link]("data inválida: %d/%d/%d", dia, mes, ano)
}
return &DataImuvel{dia, mes, ano}, nil
}

// Métodos que retornam novos valores, não modificam


func (d *DataImuvel) Adicionar_Dias(n int) *DataImuvel {
novaData := *d
[Link] += n
// Simplificado: ignora overflow de mês/ano
return &novaData
}

// Getter para visualizar


func (d *DataImuvel) Formatar() string {
return [Link]("%02d/%02d/%04d", [Link], [Link], [Link])
}

func exemplo_imutabilidade() {
d1, _ := Nova_Data(15, 3, 2024)
[Link]("Data original:", [Link]())

d2 := d1.Adicionar_Dias(10)
[Link]("Após adicionar 10 dias:", [Link]())
[Link]("Original não mudou:", [Link]())
}

// ============================================
// 6. PADRÃO BUILDER
// ============================================

// Builder para construir objetos complexos passo a passo


type RelatorioPDF struct {
Titulo string
Autor string
Conteudo string
Formato string
Compressao bool
Assinatura bool
Criptografia bool
}

type RelatorioBuilder struct {


relatorio *RelatorioPDF
}

func Novo_Relatorio_Builder() *RelatorioBuilder {


return &RelatorioBuilder{
relatorio: &RelatorioPDF{
Formato: "A4",
Compressao: false,
Assinatura: false,
Criptografia: false,
},
}
}

func (rb *RelatorioBuilder) Com_Titulo(titulo string) *RelatorioBuilder {


[Link] = titulo
return rb
}

func (rb *RelatorioBuilder) Com_Autor(autor string) *RelatorioBuilder {


[Link] = autor
return rb
}

func (rb *RelatorioBuilder) Com_Conteudo(conteudo string) *RelatorioBuilder {


[Link] = conteudo
return rb
}

func (rb *RelatorioBuilder) Com_Compressao(ativo bool) *RelatorioBuilder {


[Link] = ativo
return rb
}

func (rb *RelatorioBuilder) Com_Criptografia(ativo bool) *RelatorioBuilder {


[Link] = ativo
return rb
}

func (rb *RelatorioBuilder) Construir() *RelatorioPDF {


// Validação antes de construir
if [Link] == "" {
[Link]("Título é obrigatório")
}
return [Link]
}

func exemplo_builder() {
relatorio := Novo_Relatorio_Builder().
Com_Titulo("Relatório Mensal").
Com_Autor("João Silva").
Com_Conteudo("Dados do mês de março").
Com_Compressao(true).
Com_Criptografia(true).
Construir()

[Link]("Relatório: %v\n", relatorio)


}

// ============================================
// 7. PADRÃO FUNCTIONAL OPTIONS
// ============================================

// Options pattern para configuração flexível


type Servidor struct {
Host string
Porta int
Timeout int
Debug bool
MaxConn int
}

// Option é uma função que modifica um Servidor


type Option func(*Servidor)

func Com_Host(host string) Option {


return func(s *Servidor) {
[Link] = host
}
}

func Com_Porta(porta int) Option {


return func(s *Servidor) {
[Link] = porta
}
}

func Com_Timeout(timeout int) Option {


return func(s *Servidor) {
[Link] = timeout
}
}

func Com_Debug(debug bool) Option {


return func(s *Servidor) {
[Link] = debug
}
}

func Com_Max_Conexoes(max int) Option {


return func(s *Servidor) {
[Link] = max
}
}

// Constructor que aceita variadic options


func Novo_Servidor(opts ...Option) *Servidor {
s := &Servidor{
Host: "localhost",
Porta: 8080,
Timeout: 30,
Debug: false,
MaxConn: 100,
}

// Aplicar cada opção


for _, opt := range opts {
opt(s)
}

return s
}

func exemplo_functional_options() {
// Configuração flexível
servidor := Novo_Servidor(
Com_Host("[Link]"),
Com_Porta(3000),
Com_Debug(true),
Com_Max_Conexoes(1000),
)

[Link]("Servidor: %v\n", servidor)


}

// ============================================
// 11. TAGS DE STRUCT
// ============================================

type Pessoa struct {


ID int `json:"id" db:"pessoa_id"`
Nome string `json:"nome" db:"nome" validate:"required,min=3"`
Email string `json:"email" db:"email" validate:"email"`
Idade int `json:"idade" db:"idade" validate:"min=0,max=150"`
Ativo bool `json:"ativo" db:"ativo"`
Tags []string `json:"tags,omitempty" db:"-"` // "-" significa ignorar
em DB
}
// Lê a tag de um campo
func obter_nome_db(campo string) string {
// Simplificado: em produção use reflection package
pessoas := Pessoa{}
t := [Link](pessoas)
f, _ := [Link](campo)
return [Link]("db")
}

func exemplo_tags() {
p := Pessoa{
ID: 1,
Nome: "João Silva",
Email: "joao@[Link]",
Idade: 30,
Ativo: true,
Tags: []string{"golang", "backend"},
}

// Marshal para JSON


jsonBytes, _ := [Link](p, "", " ")
[Link]("JSON:")
[Link](string(jsonBytes))

// Unmarshal de JSON
jsonStr :=
`{"id":2,"nome":"Maria","email":"maria@[Link]","idade":28,"ativo":true}`
var p2 Pessoa
[Link]([]byte(jsonStr), &p2)
[Link]("Unmarshaled:", [Link])
}

// ============================================
// 12. CUSTOM MARSHALERS
// ============================================

type Data struct {


Dia, Mes, Ano int
}

// MarshalJSON customiza como Data é convertida para JSON


func (d Data) MarshalJSON() ([]byte, error) {
dateStr := [Link](`"%04d-%02d-%02d"`, [Link], [Link], [Link])
return []byte(dateStr), nil
}

// UnmarshalJSON customiza como JSON é convertida para Data


func (d *Data) UnmarshalJSON(data []byte) error {
dateStr := [Link](string(data), `"`)
parts := [Link](dateStr, "-")
if len(parts) != 3 {
return [Link]("formato de data inválido")
}

ano, _ := [Link](parts[0])
mes, _ := [Link](parts[1])
dia, _ := [Link](parts[2])
[Link] = ano
[Link] = mes
[Link] = dia
return nil
}

type Evento struct {


Nome string `json:"nome"`
Data Data `json:"data"`
}

func exemplo_custom_marshalers() {
evento := Evento{
Nome: "Conferência Go",
Data: Data{15, 6, 2024},
}

jsonBytes, _ := [Link](evento, "", " ")


[Link]("JSON customizado:")
[Link](string(jsonBytes))

// Desserializar
jsonStr := `{"nome":"Workshop","data":"2024-03-20"}`
var evento2 Evento
[Link]([]byte(jsonStr), &evento2)
[Link]("Evento desserializado:", evento2)
}

// ============================================
// 14. VALIDAÇÃO DE DADOS
// ============================================

type Produto struct {


Nome string
Preco float64
Qtd int
}

func (p *Produto) Validar() error {


if [Link] == "" {
return [Link]("nome é obrigatório")
}
if len([Link]) < 3 {
return [Link]("nome deve ter pelo menos 3 caracteres")
}
if [Link] <= 0 {
return [Link]("preço deve ser maior que zero")
}
if [Link] < 0 {
return [Link]("quantidade não pode ser negativa")
}
return nil
}

func exemplo_validacao() {
produtos := []Produto{
{Nome: "Notebook", Preco: 3000, Qtd: 5},
{Nome: "AB", Preco: 100, Qtd: 10}, // nome curto
{Nome: "Mouse", Preco: -50, Qtd: 20}, // preço negativo
{Nome: "Teclado", Preco: 200, Qtd: -5}, // qtd negativa
}

for i, p := range produtos {


if err := [Link](); err != nil {
[Link]("Produto %d: erro - %v\n", i, err)
} else {
[Link]("Produto %d: válido\n", i)
}
}
}

// ============================================
// 18. VALUE OBJECTS
// ============================================

// Value Object: objeto imutável que representa um valor


type Email struct {
endereco string
}

func Novo_Email(endereco string) (*Email, error) {


if ![Link](endereco, "@") {
return nil, [Link]("email inválido: %s", endereco)
}
return &Email{endereco}, nil
}

func (e *Email) Valor() string {


return [Link]
}

// Igualdade é comparação de valores, não referência


func (e *Email) Igual(outro *Email) bool {
if outro == nil {
return false
}
return [Link] == [Link]
}

type Moeda struct {


valor float64
moedaStr string // "BRL", "USD", etc
}

func Novo_Moeda(valor float64, moedaStr string) (*Moeda, error) {


if valor < 0 {
return nil, [Link]("valor não pode ser negativo")
}
return &Moeda{valor, moedaStr}, nil
}

func (m *Moeda) Somar(outra *Moeda) (*Moeda, error) {


if [Link] != [Link] {
return nil, [Link]("não pode somar moedas diferentes: %s vs %s",
[Link], [Link])
}
return Novo_Moeda([Link]+[Link], [Link])
}
func exemplo_value_objects() {
email1, _ := Novo_Email("joao@[Link]")
email2, _ := Novo_Email("joao@[Link]")
email3, _ := Novo_Email("maria@[Link]")

[Link]("email1 == email2:", [Link](email2)) // true


[Link]("email1 == email3:", [Link](email3)) // false

m1, _ := Novo_Moeda(100, "BRL")


m2, _ := Novo_Moeda(50, "BRL")
m3, _ := [Link](m2)
[Link]("100 BRL + 50 BRL = 150 BRL:", [Link])
}

// ============================================
// FUNÇÃO AUXILIAR PARA REFLECTION
// ============================================

import "reflect"

func Obter_Nome_DB_Real(t [Link], nomeField string) string {


f, _ := [Link](nomeField)
return [Link]("db")
}

// ============================================
// MAIN FUNCTION
// ============================================

func main() {
[Link]("=== Estruturação de Dados em Go ===\n")

[Link]("--- Value vs Pointer ---")


exemplo_value_vs_pointer()

[Link]("\n--- Composição ---")


exemplo_composicao()

[Link]("\n--- Encapsulamento ---")


exemplo_encapsulamento()

[Link]("\n--- Imutabilidade ---")


exemplo_imutabilidade()

[Link]("\n--- Builder Pattern ---")


exemplo_builder()

[Link]("\n--- Functional Options ---")


exemplo_functional_options()

[Link]("\n--- Tags de Struct ---")


exemplo_tags()

[Link]("\n--- Custom Marshalers ---")


exemplo_custom_marshalers()

[Link]("\n--- Validação ---")


exemplo_validacao()
[Link]("\n--- Value Objects ---")
exemplo_value_objects()
}

Você também pode gostar