Propagação de context

Propagar o mesmo context por toda uma aplicação pode fazer sentido em alguns casos, mas não é uma prática ideal ou recomendada para todas as situações. O context deve ser utilizado cuidadosamente e com objetivos específicos.

Nesse post, vamos explorar os cenários e cuidados ao se utilizar propagação de context.

O package context

O package context é parte da biblioteca padrão do Go e foi introduzido para resolver problemas relacionados ao gerenciamento de deadlines e cancelamentos em goroutines.

Ele fornece uma maneira de passar informações importantes, como limites de tempo e sinais de cancelamento, por meio de chamadas de funções e entre diferentes partes do código.

Para entender um pouco mais sobre esse package, recomendo a leitura dos posts:

Leia mais »

Como gerar PDFs

Os PDFs são amplamente utilizados para compartilhar documentos de maneira consistente e confiável. Seja para gerar relatórios, faturas ou certificados, criar PDFs programaticamente é uma necessidade comum em muitas aplicações modernas.

O vasto universo open source de packages Go oferece várias bibliotecas para manipulação de PDFs. Um dos mais populares é o gopdf, que fornece uma API intuitiva para criar PDFs sem a necessidade de packages externos pesados ou dependência de outros softwares instalados no sistema.

Neste post, você aprenderá como usar o gopdf para criar, personalizar e exportar PDFs em Go. Vamos explorar desde um exemplo simples até recursos mais avançados, como adicionar imagens e tabelas, além de exportar PDFs via HTTP.

O package gopdf

O gopdf é um package poderoso e leve para gerar PDFs em Go. Projetado para ser simples e eficiente, ele oferece uma variedade de funcionalidades:

Leia mais »

Como comparar valores em Go

Comparar valores é uma das operações mais comuns em qualquer linguagem de programação, e em Go não é diferente. Porém, a simplicidade da linguagem esconde algumas nuances importantes sobre como certos tipos podem ou não ser comparados diretamente.

Neste post, exploraremos os operadores de comparação em Go, suas limitações e alternativas.

Operadores de Comparação

De modo geral, Go oferece dois operadores para comparação direta de valores:

  • ==: Verifica se os valores dos dois operandos são iguais.
  • !=: Verifica se os valores dos dois operandos são diferentes.

Esses operadores funcionam para os tipos chamados de “comparáveis”, como por exemplo o boolean, int, float, tipos complexos, string, channels, arrays, structs e ponteiros.

Para os tipos numéricos (int, float e tipos complexos) também podemos utilizar >, <, <= e >=.

Leia mais »

Melhores práticas na utilização de ENUMs

Em linguagens de programação, enums (abreviação de enumerations) são amplamente utilizados para representar conjuntos de valores nomeados. No Go, embora não exista um tipo enum nativo, podemos alcançar um comportamento similar usando constantes tipadas.

Embora já haja um post aqui no blog sobre esse tema, resolvi criar uma versão atualizada dele onde iremos, além de explorar como implementar enums em Go, veremos as diferenças em relação a outras linguagens, e as melhores práticas na hora de utilizá-los.

ENUM em Go vs Outras Linguagens

Linguagens como Java e C# oferecem suporte nativo a enums, permitindo a criação de tipos enumerados com validação e métodos associados, como podemos ver no exemplo abaixo:

public enum Color {
    RED, GREEN, BLUE;
}
Leia mais »

Memory leaks em maps

Continuando nossa série de posts sobre garbage collector e memory leaks em Go, neste post exploraremos o que são maps e como acontecem seus memory leaks.

Antes de ler esse post, convido a ler os posts anteriores da série:

O que são maps

Map é uma estrutura chave-valor não ordenada, altamente eficientes e que baseia na estrutura de dados hash table. Internamente, uma hash table nada mais é do que um array de buckets, onde cada bucket é um ponteiro para um array chave-valor.

Cada array chave-valor tem um tamanho fixo de 8 elementos. Quando esse array está cheio (bucket overflow), um novo array de 8 elementos é criado e “linkado” ao array anterior.

Leia mais »

Memory leaks em slices

Go é uma linguagem de programação reconhecida por sua eficiência e pelo gerenciamento automático de memória através do Garbage Collector (GC). No entanto, mesmo com essas vantagens, é possível que aplicações escritas em Go sofram de vazamentos de memória, especialmente quando se lida com slices de forma inadequada.

Neste post, exploraremos o que são memory leaks, como eles podem ocorrer em slices, e as melhores práticas para evitá-los.

O que é memory leak

Um memory leak (vazamento de memória) acontece quando um programa reserva espaço na memória para uso temporário e não o libera após o uso. Isso resulta em um consumo crescente de memória, podendo levar à degradação de desempenho ou até ao esgotamento da memória disponível, causando falhas na aplicação.

Em linguagens com gerenciamento automático de memória, como Go, o Garbage Collector é responsável por liberar a memória não utilizada. Porém, se houver referências ativas a áreas da memória que não são mais necessárias, o GC não consegue liberá-las, causando um vazamento de memória.

Leia mais »

Como funciona o Garbage Collector do Go

O Garbage Collector (GC) é um dos elementos cruciais da linguagem Go, pois foi projetado para simplificar a gestão de memória para desenvolvedores. Ao contrário de linguagens como C e C++, onde os programadores devem gerenciar a alocação e liberação de memória manualmente, o GC em Go automatiza esse processo.

Neste post, vamos explorar o funcionamento do Garbage Collector em Go, entender como ele age em diferentes cenários e identificar armadilhas que podem causar memory leaks mesmo com o GC em ação.

O que é Garbage Collector

O Garbage Collector é um mecanismo automático responsável por liberar a memória alocada para objetos que não estão mais sendo utilizados no programa. Em Go, ele atua identificando quais variáveis e estruturas de dados não são mais acessíveis ou referenciadas no código e, em seguida, liberando essa memória para que possa ser reutilizada. Isso melhora a eficiência da aplicação e evita problemas como vazamento de memória (memory leaks).

Leia mais »

Functional Options Pattern

No desenvolvimento de software, a flexibilidade na configuração de objetos é uma necessidade comum, especialmente quando lidamos com funções e estruturas que possuem múltiplos parâmetros opcionais.

Em Go, por ser uma linguagem que não suporta sobrecarga de funções e parâmetros opcionais, encontrar uma solução elegante para esse problema pode ser desafiador. É aqui que o Functional Options Pattern entra como uma abordagem eficaz e idiomática.

O que é Functional Options Pattern?

O Functional Options Pattern é um padrão de design amplamente utilizado em Go para facilitar a configuração de estruturas complexas ou funções, principalmente quando há múltiplos parâmetros opcionais. Ele permite que você construa objetos ou configure funções de maneira flexível, utilizando funções que atuam como “opções”.

Em vez de passar diretamente todos os parâmetros para o construtor ou para a função, você cria funções separadas que aplicam configurações de maneira incremental e opcional. Essa abordagem ajuda a evitar funções com longas listas de parâmetros ou a necessidade de múltiplos construtores para diferentes casos de uso.

Leia mais »

Quando utilizar generics e interfaces

A linguagem Go é amplamente conhecida por sua simplicidade e pragmatismo. O design da linguagem sempre incentivou a criação de código claro e direto, evitando abstrações desnecessárias.

Com a introdução de generics no Go 1.18, desenvolvedores agora têm mais uma ferramenta para criar abstrações poderosas e reutilizáveis. Além disso, as interfaces já desempenham um papel fundamental na criação de designs flexíveis e desacoplados.

No entanto, é preciso cautela: abstrações excessivas podem facilmente adicionar complexidade sem trazer benefícios reais.

Neste post, vamos discutir quando utilizar generics e interfaces em Go e quando é melhor evitá-los.

Leia mais »

A importância de interfaces em arquiteturas de camadas

Um código organizado é essencial para manter a facilidade em sua manutenção. Go, com sua simplicidade e eficiência, oferece diversos recursos para garantir uma arquitetura bem estruturada.

Um desses recursos é o uso de interfaces, que desempenham um papel fundamental na separação de responsabilidades e na criação de abstrações entre as camadas da aplicação.

Neste post, exploraremos como as interfaces podem ser aplicadas dentro de uma arquitetura em camadas, promovendo um código desacoplado, testável e flexível.

O que é uma arquitetura em camadas

Uma arquitetura em camadas é um padrão de design de software que divide a aplicação em diferentes camadas, onde cada uma tem uma responsabilidade específica.

Leia mais »