<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Leonardo Gregianin</title>
    <description>The latest articles on DEV Community by Leonardo Gregianin (@leogregianin).</description>
    <link>https://dev.to/leogregianin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F148916%2F647fb45a-6ce1-42f4-ab0a-44f2e998953d.jpg</url>
      <title>DEV Community: Leonardo Gregianin</title>
      <link>https://dev.to/leogregianin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leogregianin"/>
    <language>en</language>
    <item>
      <title>go is good (this is about golang)</title>
      <dc:creator>Leonardo Gregianin</dc:creator>
      <pubDate>Mon, 31 Mar 2025 12:15:00 +0000</pubDate>
      <link>https://dev.to/leogregianin/go-is-good-this-is-about-golang-1kha</link>
      <guid>https://dev.to/leogregianin/go-is-good-this-is-about-golang-1kha</guid>
      <description>&lt;p&gt;A few days ago, I came across the repository "&lt;a href="https://github.com/ksimka/go-is-not-good" rel="noopener noreferrer"&gt;go-is-not-good&lt;/a&gt;", which contains several articles with negative views about Golang. After analyzing and reading all the points, I wrote this article highlighting the positive points of the language.&lt;/p&gt;

&lt;p&gt;Go, often called Golang, is a modern programming language that stands out for its simplicity, efficiency, and scalability. Designed by Google, Go was created to address common challenges in software development, making it an excellent choice for developers who need a powerful yet easy-to-use language. Here's why Go is a fantastic programming language:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Simplicity and Readability
&lt;/h2&gt;

&lt;p&gt;One of the most significant advantages of Go is its simplicity. Unlike many other languages that come with complex syntax and unnecessary features, Go focuses on keeping things straightforward. This simplicity makes Go easy to learn, read, and maintain, which is especially beneficial for teams and large-scale projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Fast Compilation and Execution
&lt;/h2&gt;

&lt;p&gt;Go is a compiled language, meaning it translates code directly into machine code, resulting in fast execution. The Go compiler is incredibly efficient, enabling rapid compilation times that significantly boost development speed. This makes Go an excellent choice for performance-critical applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Built-in Concurrency Support
&lt;/h2&gt;

&lt;p&gt;Concurrency is a first-class citizen in Go. With goroutines and channels, Go makes it easier than ever to write concurrent programs. Goroutines are lightweight threads managed by the Go runtime, allowing developers to efficiently handle multiple tasks at once without the complexity of traditional threading models.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Strong Standard Library
&lt;/h2&gt;

&lt;p&gt;Go comes with a powerful standard library that covers a wide range of functionalities, including networking, file handling, and cryptography. The standard library is well-designed, reducing the need for third-party dependencies and ensuring consistency across projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Garbage Collection for Memory Management
&lt;/h2&gt;

&lt;p&gt;Go's garbage collector ensures that developers don't have to manually manage memory, reducing the risk of memory leaks and improving application stability. The garbage collection mechanism is optimized for performance, making Go an excellent choice for applications that require efficient memory management.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Static Typing with Simplicity
&lt;/h2&gt;

&lt;p&gt;Go is statically typed, which helps catch errors early in the development process. However, it avoids the verbosity of other statically typed languages, striking a balance between type safety and ease of use.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Excellent Tooling and Ecosystem
&lt;/h2&gt;

&lt;p&gt;Go provides built-in tools for formatting, testing, and performance analysis. Features like go fmt, go test, and go vet streamline the development workflow, ensuring high code quality with minimal effort. The Go ecosystem also includes robust package management with go mod and a thriving community that continuously contributes to its growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Cross-Platform Compilation
&lt;/h2&gt;

&lt;p&gt;Go's ability to compile applications for different platforms (Windows, Linux, macOS) with a simple command makes it an attractive choice for developers building cross-platform applications. This feature eliminates the need for complex build processes and ensures seamless deployment across various environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Cloud and Microservices-Friendly
&lt;/h2&gt;

&lt;p&gt;Go is widely used in cloud computing and microservices architectures due to its efficiency and scalability. Many modern cloud-native platforms, including Kubernetes and Docker, are written in Go, showcasing its suitability for building scalable and high-performance services.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Backed by Google and a Strong Community
&lt;/h2&gt;

&lt;p&gt;Go is backed by Google, ensuring ongoing support and continuous improvement. Additionally, the Go community is active and supportive, providing a wealth of resources, open-source projects, and forums where developers can collaborate and learn from one another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Go is a powerful and pragmatic programming language that excels in simplicity, performance, and scalability. Whether you're building high-performance web services, cloud-native applications, or system-level utilities, Go provides the right balance of efficiency and ease of use. Its growing adoption in the tech industry is a testament to its strengths, making it a top choice for modern software development.&lt;/p&gt;

&lt;p&gt;If you want to know more details about go features, see the repository and click on the star: &lt;a href="https://github.com/leogregianin/go-is-good" rel="noopener noreferrer"&gt;https://github.com/leogregianin/go-is-good&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>software</category>
    </item>
    <item>
      <title>Kubernetes: o que é, quando e como aplicá-lo</title>
      <dc:creator>Leonardo Gregianin</dc:creator>
      <pubDate>Wed, 03 Jan 2024 18:08:00 +0000</pubDate>
      <link>https://dev.to/leogregianin/kubernetes-o-que-e-quando-e-como-aplica-lo-1h6c</link>
      <guid>https://dev.to/leogregianin/kubernetes-o-que-e-quando-e-como-aplica-lo-1h6c</guid>
      <description>&lt;h2&gt;
  
  
  O que é Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Kubernetes é uma plataforma de orquestração de contêineres de código aberto. Ele automatiza o deploy, a escalabilidade e o gerenciamento de aplicativos em contêineres.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzq4fu4mta1oksf10r73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzq4fu4mta1oksf10r73.png" alt="k8s logo" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Qual a sua origem?
&lt;/h2&gt;

&lt;p&gt;O Kubernetes iniciou como um sistema interno de orquestração de contêineres no Google, chamado Borg, que gerenciava a implantação de milhares de aplicativos no Google. Em 2014, o Google abriu o código-fonte de uma versão do Borg e o denominou como Kubernetes, que em grego (&lt;code&gt;κυβερνήτης&lt;/code&gt;) significa "timoneiro" ou "piloto" e agora é mantido pela Cloud Native Computing Foundation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Porque alguns o chamam de K8S?
&lt;/h2&gt;

&lt;p&gt;Esta é uma maneira um tanto nerd de abreviar palavras longas. O número 8 em K8S refere-se às oito letras entre a primeira letra K e a última letra S na palavra Kubernetes. Outros exemplos são I18N para internacionalização e L10N para localização.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quais as principais peças de um cluster K8S?
&lt;/h2&gt;

&lt;p&gt;Um cluster Kubernetes é um conjunto de máquinas chamadas "nós" que são usadas para executar aplicativos em contêineres. Existem duas peças principais em um cluster Kubernetes, vejamos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O primeiro é o &lt;strong&gt;plano de controle&lt;/strong&gt; ou &lt;strong&gt;control plane&lt;/strong&gt; que é responsável por gerenciar o estado do cluster. Em ambientes de produção, o control plane geralmente é executado em vários nós que abrangem diversas zonas do data center. Em ambientes on-premisse você mesmo deve ter o controle sobre ele, em ambientes cloud providers como AWS, Google Cloud ou Azure, a própria cloud gerencia o control plane.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O segundo é um conjunto de &lt;strong&gt;nós de trabalho&lt;/strong&gt; ou &lt;strong&gt;worker&lt;/strong&gt;. Esses nós executam as cargas de trabalho de aplicativos em contêineres. Os aplicativos em contêineres são executados em um "pod". Os pods são as menores unidades de um cluster Kubernetes. Um pod hospeda um ou mais contêineres e fornece armazenamento compartilhado e rede para esses contêineres. Os pods são criados e gerenciados pelo control plane do Kubernetes. Eles são os blocos de construção básicos dos aplicativos Kubernetes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudig27an2zle5jg2wsp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudig27an2zle5jg2wsp8.png" alt="architeture" width="531" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Control Plane
&lt;/h2&gt;

&lt;p&gt;Plano de Controle consiste em vários componentes principais. Eles são o Servidor API (&lt;strong&gt;API Server&lt;/strong&gt;), o &lt;strong&gt;etcd&lt;/strong&gt;, o agendador (&lt;strong&gt;Scheduler&lt;/strong&gt;) e o gerenciador de controle (&lt;strong&gt;Controller Manager&lt;/strong&gt;). O API Server é a principal interface de comunicação entre Control Plane e o restante do Cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d7f8kzj5irw2bnawghq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d7f8kzj5irw2bnawghq.png" alt="control plane" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Control Plane expõe uma &lt;strong&gt;API&lt;/strong&gt; RESTful que permite aos clientes interagir com o Control Plane e enviar solicitações para gerenciar o cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;etcd&lt;/strong&gt; é um armazenamento de chave-valor distribuído, ou seja, é o estado persistente do cluster. É utilizado pela API Server e outros componentes do Control Plane para armazenar e recuperar informações sobre o cluster.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Scheduler&lt;/strong&gt; é responsável por agendar pods nos nós dos workers do cluster. Ele usa informações sobre os recursos exigidos pelos pods e os recursos disponíveis nos nós do worker para tomar decisões.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Controller Manager&lt;/strong&gt; é responsável por executar controladores que gerenciam o estado do cluster, por exemplo, o controlador de réplicas, que garante que o número desejado de réplicas de um pod esteja em execução, e um controlador de deploy, que gerencia as atualizações contínuas e reversões de deploys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worker
&lt;/h2&gt;

&lt;p&gt;Os principais componentes do Kubernetes executados nos worker nodes incluem &lt;strong&gt;kubelet&lt;/strong&gt;, &lt;strong&gt;container runtime&lt;/strong&gt; e o &lt;strong&gt;kubeproxy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftp0cjr5m77554fw6vlws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftp0cjr5m77554fw6vlws.png" alt="worker" width="346" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;kubelet&lt;/strong&gt; é um daemon executado em cada worker node e é responsável pela comunicação com o Control Plane recebendo instruções de quais pods serão executados no nó e garante que o estado desejado dos pods seja mantido.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Container runtime&lt;/strong&gt; executa os contêineres nos worker nodes e é responsável por extrair as imagens dos contêineres de um registro, iniciar, parar e gerenciar os recursos dos contêineres.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;kubeproxy&lt;/strong&gt; é um proxy de rede executado em cada wroker node e é responsável por rotear o tráfego para os pods corretos, realiza balanceamento de carga para os pods e garante que o tráfego seja distribuído uniformemente entre os pods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vantagens
&lt;/h2&gt;

&lt;p&gt;Kubernetes é escalonável e altamente disponível, fornece recursos como autocorreção, reversões automáticas e dimensionamento horizontal. Isso torna mais fácil aumentar ou diminuir nosso aplicativo conforme necessário, permitindo-nos responder rapidamente às mudanças na demanda.&lt;/p&gt;

&lt;p&gt;Kubernetes é portátil, nos ajuda a implantar e gerir aplicações de forma consistente e confiável, independentemente da infraestrutura. Ele é executado on-premise, em cloud ou em ambiente híbrido. Fornece uma maneira uniforme de empacotar, implantar e gerenciar aplicativos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Desvantagens
&lt;/h2&gt;

&lt;p&gt;A desvantagem número um é a complexidade. O Kubernetes é complexo de configurar e operar. O custo inicial é alto para formar uma equipe com conhecimento em orquestração de contêineres. Requer um alto nível de conhecimento e recursos para configurar e gerenciar um ambiente de produção do Kubernetes.&lt;/p&gt;

&lt;p&gt;A segunda desvantagem é o custo. O Kubernetes requer um certo nível mínimo de recursos para funcionar, a fim de oferecer suporte a todos os recursos mencionados acima. Provavelmente é um exagero para aplicações menores.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opção razoável
&lt;/h2&gt;

&lt;p&gt;Uma opção popular que atinge um equilíbrio razoável é transferir o gerenciamento do control plane para um serviço gerenciado do Kubernetes em um cloud provider como Amazon EKS, GKE no Google Cloud e AKS no Azure. Esses serviços permitem que as organizações executem aplicativos Kubernetes sem se preocupar com a infraestrutura.&lt;/p&gt;

&lt;p&gt;Eles cuidam de tarefas que exigem conhecimento profundo, como instalar e configurar o control plane, dimensionar o cluster e fornecer manutenção e suporte contínuos. Esta é uma opção razoável para uma organização de médio porte testar o Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo em código
&lt;/h2&gt;

&lt;p&gt;Como exemplo, fizemos uma aplicação real chamada &lt;strong&gt;URL shorter&lt;/strong&gt;, ou, &lt;strong&gt;Encurtador de URL&lt;/strong&gt; que recebe uma URL e retorna um hash da URL original tornando uma URL curta, que ao ser acessada redireciona para a URL original e grava a quantidade de acessos a URL curta e a URL original.&lt;/p&gt;

&lt;p&gt;Por exemplo, a URL de um dos meus artigos no Medium é essa: &lt;code&gt;https://dev.to/leogregianin/python-e-facil-go-e-simples-simples-e-diferente-de-facil-5b9o&lt;/code&gt; e poderia ficar somente &lt;code&gt;https://encurtador_de_url.com/abc123&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O objetivo é mostrar como é possível criar uma aplicação utilizando as melhores práticas de desenvolvimento e deploy, utilizando as tecnologias &lt;strong&gt;Django&lt;/strong&gt; para backend e frontend, &lt;strong&gt;Django Rest Framework&lt;/strong&gt; para API, &lt;strong&gt;Postgres&lt;/strong&gt; como banco de dados e &lt;strong&gt;Docker&lt;/strong&gt; e &lt;strong&gt;Kubernetes&lt;/strong&gt; para containerização e orquestração do deploy.&lt;/p&gt;

&lt;p&gt;URL shorter é uma aplicação pequena e é utilizada para fins didáticos de como construir uma aplicação e escalar ela utilizando Kubernetes.&lt;/p&gt;

&lt;p&gt;Um único pod:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zxax2qbhbcibpv9rx9q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zxax2qbhbcibpv9rx9q.png" alt="one_pod" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Escalando para 12 réplicas:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fef4b3msic6843ytfi0k9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fef4b3msic6843ytfi0k9.png" alt="scaling" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;App rodando:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqh198uozn9n25qlv21k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqh198uozn9n25qlv21k.png" alt="app" width="495" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O código da aplicação e os arquivos de configuração do Docker e Kubernetes estão em: &lt;a href="https://github.com/leogregianin/kubernetes-workshop" rel="noopener noreferrer"&gt;https://github.com/leogregianin/kubernetes-workshop&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
      <category>python</category>
      <category>django</category>
    </item>
    <item>
      <title>Python é fácil. Go é simples. Simples é diferente de fácil</title>
      <dc:creator>Leonardo Gregianin</dc:creator>
      <pubDate>Tue, 12 Dec 2023 15:08:00 +0000</pubDate>
      <link>https://dev.to/leogregianin/python-e-facil-go-e-simples-simples-e-diferente-de-facil-5b9o</link>
      <guid>https://dev.to/leogregianin/python-e-facil-go-e-simples-simples-e-diferente-de-facil-5b9o</guid>
      <description>&lt;p&gt;&lt;cite&gt;Tradução livre do artigo “Python is Easy. Go is Simple. Simple != Easy” escrito por Preslav Rachev no seu blog. O artigo original pode ser lido em: &lt;a href="https://preslav.me/2023/11/27/python-is-easy-golang-is-simple-simple-is-not-easy/" rel="noopener noreferrer"&gt;https://preslav.me/2023/11/27/python-is-easy-golang-is-simple-simple-is-not-easy/&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;

&lt;p&gt;Existe um equívoco comum de que simples e fácil se referem à mesma coisa. Afinal, se algo é fácil de usar, seu funcionamento interno deve ser simples de entender, certo? Ou vice-versa? Na verdade, é exatamente o oposto. Embora os dois conceitos apontem para o mesmo resultado, fazer algo parecer fácil requer uma enorme complexidade.&lt;/p&gt;

&lt;p&gt;Tomemos como exemplo o Python, uma linguagem conhecida por sua baixa barreira de entrada e, portanto, uma escolha favorita para linguagem de programação de entrada. Escolas, universidades, centros de pesquisa e um grande número de empresas em todo o mundo escolheram Python precisamente por causa de sua acessibilidade a qualquer pessoa, independentemente do seu nível de educação ou formação acadêmica (ou total falta dela). Raramente é necessária muita teoria de tipos ou compreensão de como e onde as coisas são armazenadas na memória, em quais threads algum trecho de código está sendo executado, etc. Além disso, Python é a porta de entrada para algumas das mais profundas bibliotecas científicas e de nível de sistema. Ser capaz de controlar essa quantidade de poder com uma única linha de código fala muito a favor de que ela se torne uma das linguagens de programação mais populares do planeta.&lt;/p&gt;

&lt;p&gt;E aí vem o problema: a facilidade de expressar coisas em código Python tem um custo. Por baixo dos panos, o interpretador Python é enorme e muitas operações devem ocorrer para que até mesmo uma única linha de código seja executada. Quando você ouve alguém se referindo ao Python como uma linguagem “lenta”, grande parte da “lentidão” percebida vem do número de decisões que o interpretador toma em tempo de execução. Mas esse nem é o maior problema, na minha opinião. A complexidade do ecossistema de tempo de execução do Python, juntamente com algumas decisões liberais de design em torno do gerenciamento de pacotes, cria um ambiente muito frágil, e as atualizações geralmente levam a incompatibilidades e travamentos de tempo de execução. Não é incomum deixar um aplicativo Python para voltar a ele depois de alguns meses, apenas para perceber que o ambiente mudou o suficiente para que não seja mais possível nem mesmo iniciar o aplicativo.&lt;/p&gt;

&lt;p&gt;Claro, isso é uma simplificação grosseira, e até as crianças de hoje em dia sabem que existem contêineres para resolver problemas como esse. Na verdade, graças ao Docker e similares, é possível “congelar” as dependências de uma base de código Python no tempo para que ela possa praticamente rodar para sempre. No entanto, isso tem o custo de transferir a responsabilidade e a complexidade para a infraestrutura do sistema operacional. Não é o fim do mundo, mas também não é algo que deva ser subestimado e ignorado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Da facilidade à simplicidade
&lt;/h2&gt;

&lt;p&gt;Se resolvêssemos os problemas com Python, acabaríamos com algo como Rust — extremamente performático, mas com uma barreira de entrada notoriamente alta. A ferrugem, na minha opinião, não é fácil de usar e, o que é mais importante, não é simples. Embora esteja em alta hoje em dia, apesar de 20 anos de programação e de ter dado meus primeiros passos em C e C++, não posso olhar para um pedaço de código Rust e dizer com certeza que entendo o que está acontecendo lá.&lt;/p&gt;

&lt;p&gt;Descobri Go há cerca de cinco anos, enquanto trabalhava em um sistema baseado em Python. Embora tenha levado algumas tentativas para gostar da sintaxe, imediatamente caí na ideia de simplicidade. O objetivo do Go é ser simples de entender por qualquer pessoa em uma organização — desde o desenvolvedor júnior recém-saído da escola até o gerente de engenharia de nível sênior que apenas ocasionalmente olha o código. Além do mais, sendo uma linguagem simples, Go raramente recebe atualizações de sintaxe — a última significativa foi a adição de genéricos na v1.18, o que ocorre somente após uma década de discussões sérias. Na maior parte, quer você observe o código Go escrito há cinco dias ou cinco anos, ele é basicamente o mesmo e deve funcionar.&lt;/p&gt;

&lt;p&gt;A simplicidade requer disciplina. Pode parecer limitante e até um tanto retrógrado no início. Especialmente quando comparado a uma expressão sucinta, como uma lista ou compreensão de dicionário em Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;temperatures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;City1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;City2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;City3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;filtered_temps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;temperatures&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O mesmo código em Go requer mais código, mas idealmente deve ser uma ideia mais próxima do que o interpretador Python está fazendo por baixo dos panos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;CityTemperature&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Temp&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// ...&lt;/span&gt;

&lt;span class="n"&gt;temperatures&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;CityTemperature&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"City1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"City2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"City3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;filteredTemps&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;temperatures&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Temp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;filteredTemps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Temp&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Embora você possa escrever código equivalente em Python, uma regra não escrita em programação diz que se a linguagem fornecer uma opção mais fácil (mais concisa, mais elegante), os programadores irão gravitar em torno dela. Mas fácil é subjetivo e simples deve ser igualmente aplicável a todos. A disponibilidade de alternativas para executar a mesma ação leva a diferentes estilos de programação, e muitas vezes é possível encontrar vários estilos na mesma base de código.&lt;/p&gt;

&lt;p&gt;Como Go é prolixo e “chato”, ele naturalmente marca outra caixa — o compilador Go tem muito menos trabalho a fazer ao compilar um executável. Compilar e executar um aplicativo Go costuma ser tão rápido, ou até mais rápido, do que carregar o interpretador Python ou a máquina virtual Java antes mesmo de executar o aplicativo real. Não é de surpreender que ser um executável nativo seja tão rápido quanto um executável pode ser. Não é tão rápido quanto seus equivalentes em C/C++ ou Rust, mas com uma fração da complexidade do código. Estou disposto a negligenciar esta pequena “desvantagem” do Go. Por último, mas não menos importante, os binários Go são vinculados estaticamente, o que significa que você pode construir um em qualquer lugar e executá-lo no host de destino — sem quaisquer tempos de execução ou dependências de biblioteca. Por uma questão de conveniência, ainda agrupamos nossos aplicativos Go em contêineres Docker. Ainda assim, eles são significativamente menores e têm uma fração do consumo de memória e CPU de seus equivalentes Python ou Java.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como usamos Python e Go a nosso favor
&lt;/h2&gt;

&lt;p&gt;A solução mais pragmática que encontramos em nosso trabalho é combinar os poderes da facilidade do Python e da simplicidade do Go. Para nós, Python é um ótimo playground de prototipagem. É onde nascem as ideias e onde as hipóteses científicas são aceitas e rejeitadas. Python é uma escolha natural para ciência de dados e aprendizado de máquina e, como lidamos com muitas dessas coisas, não faz sentido tentar reinventar a roda com outra coisa. Python também tem o Django, que atende ao seu lema de permitir o desenvolvimento rápido de aplicativos como poucas outras ferramentas (é claro, Ruby on Rails e Elixir’s Phoenix merecem uma menção digna de nota aqui).&lt;/p&gt;

&lt;p&gt;Suponha que um projeto precise de um mínimo de gerenciamento de usuários e administração interna de dados (como a maioria dos nossos projetos). Nesse caso, começaríamos com um esqueleto do Django por causa do seu Admin integrado, o que é fantástico. Uma vez que a prova de conceito com Django começa a se assemelhar a um produto, identificamos o quanto dele pode ser reescrito em Go. Como o aplicativo Django já definiu a estrutura do banco de dados e a aparência dos modelos de dados, escrever o código Go que o complementa é bastante fácil. Depois de algumas iterações, chegamos a uma simbiose, onde os dois lados coexistem pacificamente no mesmo banco de dados e usam mensagens básicas para se comunicarem. Eventualmente, o “shell” do Django se torna um orquestrador — ele serve aos nossos propósitos de administração e aciona tarefas que são então gerenciadas pela sua contraparte Go. A parte Go atende a todo o resto, desde APIs e endpoints até a lógica de negócios e processamento de trabalhos em background.&lt;/p&gt;

&lt;p&gt;É uma simbiose que tem funcionado bem até agora e espero que continue assim no futuro. Em um post futuro, descreverei mais alguns detalhes sobre a arquitetura em si.&lt;/p&gt;

&lt;p&gt;Obrigado por ler!&lt;/p&gt;

</description>
      <category>python</category>
      <category>go</category>
      <category>django</category>
    </item>
  </channel>
</rss>
