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 »

Por que evitar o uso da função init

Nas últimas semanas, tenho focado muito em escrever sobre o que evitar na hora de escrever programas Go.

Tenho feito isso pois, em alguns casos, o melhor que se pode saber sobre uma feature ou package é exatamente quando não utilizar.

Por isso, dando continuidade nesse tipo de post, neste, vamos explorar o que é a função init, como ela funciona, porque seu uso pode ser problemático e quando ela deve ser utilizada de forma consciente.

O que é e para que serve a função init

A função init em Go é uma função especial que é automaticamente executada pelo runtime antes da função main, sem a necessidade de ser chamada explicitamente.

Leia mais »

Por que evitar panic e recover em produção

No desenvolvimento de software, especialmente em linguagens como Go, garantir a estabilidade e a resiliência da aplicação é essencial, especialmente em ambientes de produção.

Uma das funcionalidades controversas do Go é o uso de panic e recover. Apesar de serem recursos poderosos, o uso inadequado deles pode levar a sérios problemas em produção.

Neste post, exploraremos o que são panic e recover, suas implicações e por que você deve evitá-los em ambientes de produção.

O que é panic?

Em Go, panic é uma função que interrompe a execução normal da aplicação, imediatamente propagando um erro até o ponto mais alto da pilha de chamadas (stack). Quando uma função chama panic, a execução da função é interrompida, qualquer função chamada com defer é executada e o programa se encerra (a menos que o panic seja recuperado com recover).

Leia mais »

Por que evitar o package Reflect

O package reflect no Go é uma ferramenta poderosa que permite inspecionar e manipular tipos e valores em runtime. No entanto, como diria o tio Ben, “com grandes poderes vêm grandes responsabilidades”.

Embora possa parecer atraente em certos cenários, o uso excessivo ou inadequado do reflect pode introduzir problemas significativos no seu código, como dificuldades de manutenção, bugs difíceis de depurar e perda de performance.

Neste post, exploraremos o que é o package reflect, exemplos de sua utilização, onde ele é amplamente empregado e, mais importante, porque você deve evitá-lo quando possível.

O que é o package Reflect

O package reflect faz parte da biblioteca padrão do Go e oferece funcionalidades para inspecionar tipos e valores em runtime, ou seja, em tempo de execução.

Leia mais »

Dicas para escrever bons benchmarks

Escrever benchmarks em Go é uma prática essencial para desenvolvedores que buscam otimizar a performance de suas aplicações.

Um benchmark bem elaborado pode revelar gargalos e oportunidades de otimização que, de outra forma, poderiam passar despercebidos.

No entanto, existem armadilhas comuns que podem distorcer os resultados dos benchmarks, levando a conclusões incorretas.

Neste post, exploraremos os principais cuidados que devem ser tomados ao escrever benchmarks em Go, com exemplos de código que ilustram boas e más práticas.

Importância de escrever Benchmarks

Benchmarking é uma técnica que permite medir a eficiência de determinadas partes do código, como funções ou métodos, em termos de tempo de execução.

Ao escrever benchmarks, você pode identificar quais partes do código precisam ser otimizadas e quais já estão suficientemente rápidas. No contexto de desenvolvimento de software, benchmarks são fundamentais para garantir que mudanças no código não degradem a performance.

Leia mais »

Integrando aplicações Go com ChatGPT

Com o avanço das tecnologias de inteligência artificial, cada vez mais desenvolvedores buscam integrar suas aplicações com APIs de IA para oferecer funcionalidades avançadas e personalizadas.

Uma dessas APIs é a do ChatGPT, desenvolvida pela OpenAI, que permite gerar texto de forma natural e coerente. Neste post, vou mostrar como você pode integrar uma aplicação Go com a API do ChatGPT para criar uma funcionalidade onde o usuário insere um valor monetário e a aplicação retorna esse valor por extenso.

Pré-requisitos para a Integração

Antes de iniciar a integração, é necessário cumprir alguns pré-requisitos:

  1. Conta na OpenAI: Você precisará de uma conta na OpenAI para acessar a API do ChatGPT.
  2. API Key: Após criar sua conta, você deve gerar uma chave de API (API Key) no painel de controle da OpenAI.
Leia mais »

O que é e como utilizar o package context

No desenvolvimento de aplicações em Go, é comum enfrentar situações em que precisamos gerenciar o tempo de vida de processos, propagar cancelamentos de tarefas ou passar dados entre goroutines.

Para resolver esses problemas, a própria linguagem fornece um package chamado context.

Nesse post, vamos explorar juntos o que é o package context, para que ele serve, onde normalmente é utilizado e como implementá-lo em suas aplicações Go.

Hello Context

O package context foi introduzido na versão 1.7 do Go e é utilizado para gerenciar deadlines, cancelamentos e outros valores através de limites de API e entre goroutines. Sua principal função é gerenciar o tempo de vida de uma operação, especialmente em servidores e aplicativos web, onde operações longas podem ser canceladas se excederem um determinado tempo ou se a solicitação do cliente for cancelada.

Leia mais »

A diferença entre ponteiro e valor nos métodos

Quando escrevemos métodos em Go, uma das decisões importantes é se devemos passar a struct por valor ou por ponteiro. A escolha pode impactar a performance, o comportamento do nosso código e a alocação de memória. Neste post, vamos explorar essa diferença com um exemplo prático e entender em quais situações cada abordagem é mais adequada.

Vamos começar com uma pequena struct e dois métodos: um onde a struct é passada por valor e outro por ponteiro.

Leia mais »