Boas Práticas e Padrões Idiomáticos em Go e C

Nem sempre boas práticas são consideradas design patterns formais. Porém, quando uma técnica se torna a única forma eficaz de resolver problemas recorrentes, ela deixa de ser apenas "higiene de código" e passa a funcionar como um padrão idiomático da linguagem.

Este documento explora como structs, composição e interfaces em Go (e até em C) podem ser vistos como soluções de design aplicando esses princípios para um bom código. O texto começa explicando o uso em C de ponteiros e faz uma analogia sobre injeção de código de POO. Este documento tem por objetivo de tornar um dia um desgin para GO ou até C, QUE SÃO PROCEDURAIS. É um exemplo onde você não resolve bem uma questão sem esse principio de que se você não usar, você não resolve da melhor maneira. O documento é trabalhado nas fases seguintes com o argumento de porque usar ou não usar para justificar um design.

[ Hits: 116 ]

Por: trogmaiu em 25/03/2026


EXPLICAÇÃO 3



Structs, composição e interfaces em Go (e até em C) podem ser vistos como soluções de design, aplicando princípios como SRP e OCP do SOLID.
Questões que não são bem resolvidas sem struct, composição e interfaces.

1.Representação de entidades complexas

Sem structs, dados relacionados ficam dispersos em variáveis soltas ou mapas.
structs permitem modelar entidades como User, Order, Config.

2. Extensibilidade sem modificar código existente (OCP)

Interfaces permitem definir contratos e criar múltiplas implementações.
Sem interfaces, seria necessário usar condicionais extensos (if/else ou switch).

3. Polimorfismo sem herança

Go não possui herança clássica, mas interfaces + composição permitem polimorfismo.
Exemplo: qualquer tipo que implemente io.Reader pode ser usado em funções que esperam um Reader.

4. Separação de responsabilidades (SRP)

Composição de structs divide responsabilidades em partes menores.
Exemplo: um Logger pode ser embutido em diferentes structs sem duplicação.

5. Testabilidade e desacoplamento

- Interfaces permitem criar mocks em testes.
- Sem elas, o código ficaria preso a implementações concretas.

Exemplos em Go Interface pequena (SRP + ISP)
type Reader interface {
    Read(p []byte) (n int, err error)
}
- Qualquer tipo que implemente pode ser usado como.
- Isso reduz acoplamento e aumenta flexibilidade.

Composição de structs (OCP)
func (l Logger) Log(msg string) {
    fmt.Println(msg)
}
type Service struct {
    Logger
}
func (s Service) DoWork() {
    s.Log("Executando tarefa...")
}
- Service reutiliza Logger sem herança.
- É possível adicionar novos comportamentos sem alterar Logger.

Paralelo em C
Em C, não há interfaces, mas é possível simular comportamentos semelhantes com structs + ponteiros de função:
int (*operation)(int, int);
} Strategy;
   int add(int a, int b) { return a + b; }
   int multiply(int a, int b) { return a * b; }
   Strategy s;
   s.operation = add;
   printf("%d\n", s.operation(2, 3)); // 5
"Aqui, Strategy funciona como uma interface.
Diferentes funções podem ser atribuídas sem mudar o código que usa Strategy."
Obs.: Para um programador C, fica subentendido que as chaves de abertura da struct e a função main estão lá.
O que importa nessa comparação é o mecanismo em si.


Questões que não são bem resolvidas sem struct, composição e interfaces.

1.Representação de entidades complexas
2. Extensibilidade sem modificar código existente (OCP).
3.Polimorfismo sem herança.
4.Separação de responsabilidades (SRP)
5. Testabilidade e desacoplamento.

Isso resolve:
Agrupar dados relacionados: structs evitam variáveis soltas e tornam entidades mais claras.
Flexibilidade com interfaces: contratos permitem múltiplas implementações sem alterar código existente.
Reuso com composição: embutir comportamentos (Logger, Config) em diferentes structs sem duplicação.
Testes mais simples: interfaces permitem mocks e reduzem acoplamento.
Polimorfismo idiomático: qualquer tipo que implemente uma interface pode ser usado em funções genéricas.

Isso não resolve:
1.Complexidade desnecessária: usar interfaces para algo que nunca terá mais de uma implementação só adiciona ruído.
2.Herança clássica: Go não tem, e tentar simular herança com composição pode gerar confusão.
3.Gerenciamento de memória avançado: structs não substituem técnicas de otimização de baixo nível (como em C).
4.Problemas de concorrência: interfaces e composição não resolvem race conditions; é preciso usar goroutines e channels.
5.Validação de dados complexa: structs ajudam a organizar, mas não substituem lógica de validação robusta.
Página anterior     Próxima página

Páginas do artigo
   1. Boas Práticas e Padrões Idiomáticos em Go e C
   2. EXPLICAÇÃO 1
   3. EXPLICAÇÃO 2
   4. EXPLICAÇÃO 3
   5. CONCLUSÃO
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Cuidado com números em Ponto Flutuante

Desenvolvendo para microcontroladores em GNU/Linux

Sinais em Linux

Bug afeta todas as distros

Compilando o Mono 2.2 no Ubuntu 8.10

  
Comentários

Nenhum comentário foi encontrado.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts