<?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: renanbastos93</title>
    <description>The latest articles on DEV Community by renanbastos93 (@renanbastos93).</description>
    <link>https://dev.to/renanbastos93</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F56622%2F00181bd0-9d1e-48c1-b1db-18d2a28a591e.jpeg</url>
      <title>DEV Community: renanbastos93</title>
      <link>https://dev.to/renanbastos93</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/renanbastos93"/>
    <language>en</language>
    <item>
      <title>Funções anônimas são mais lentas em Go? Medi os 6 cenários e só 1 custa caro</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Tue, 03 Nov 2026 17:39:14 +0000</pubDate>
      <link>https://dev.to/renanbastos93/funcoes-anonimas-sao-mais-lentas-em-go-medi-os-6-cenarios-e-so-1-custa-caro-k2i</link>
      <guid>https://dev.to/renanbastos93/funcoes-anonimas-sao-mais-lentas-em-go-medi-os-6-cenarios-e-so-1-custa-caro-k2i</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Esse é um mito extremamente comum em code review de Go, inclusive em times experientes.&lt;/p&gt;

&lt;p&gt;O roteiro é quase sempre o mesmo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;alguém roda um benchmark&lt;/li&gt;
&lt;li&gt;vê uma diferença de &lt;code&gt;ns/op&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;conclui que função anônima é mais lenta&lt;/li&gt;
&lt;li&gt;abre um PR trocando closures por funções nomeadas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na maioria dos casos, o culpado apontado é este aqui:&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;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E quase sempre o culpado é outro.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Função anônima &lt;strong&gt;não&lt;/strong&gt; é mais lenta. Medi: 1,614 ns/op nas duas versões, diferença de 0%&lt;/li&gt;
&lt;li&gt;Closure &lt;strong&gt;não&lt;/strong&gt; significa heap allocation. Capturar variável pode ficar 100% na stack&lt;/li&gt;
&lt;li&gt;Dos 6 cenários que medi, &lt;strong&gt;só 1 aloca&lt;/strong&gt;, e é 3,2× mais lento&lt;/li&gt;
&lt;li&gt;O único que aloca é a closure &lt;strong&gt;criada a cada operação&lt;/strong&gt; e que &lt;strong&gt;sobrevive&lt;/strong&gt; à função que a criou&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ns/op&lt;/code&gt; é ruído. &lt;code&gt;B/op&lt;/code&gt; e &lt;code&gt;allocs/op&lt;/code&gt; são comportamento&lt;/li&gt;
&lt;li&gt;O caso mais caro nem aparece no benchmark: closure que segura um objeto grande vivo (medi 100 MB presos por 1 byte usado)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Neste post você vai entender
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;O que realmente custa em uma closure&lt;/li&gt;
&lt;li&gt;Como provar com benchmark, escape analysis e &lt;code&gt;pprof&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Por que &lt;code&gt;ns/op&lt;/code&gt; engana e o que olhar no lugar&lt;/li&gt;
&lt;li&gt;O caso de retenção de memória que &lt;code&gt;allocs/op&lt;/code&gt; não mostra&lt;/li&gt;
&lt;li&gt;Quando usar função anônima sem medo, e quando investigar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todo o código está no fim do post. Você reproduz com um comando.&lt;/p&gt;

&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;O mito em uma linha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;função anônima = heap allocation = lento
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nenhuma das duas igualdades é verdadeira.&lt;/p&gt;

&lt;p&gt;Compare:&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="c"&gt;// nomeada&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// anônima&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O compilador enxerga a expressão inteira na segunda versão. Ele inlina as duas.&lt;/p&gt;

&lt;p&gt;Mesmo código de máquina. Mesmo custo.&lt;/p&gt;

&lt;p&gt;O custo não vem da sintaxe. Vem de outra coisa.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que realmente custa
&lt;/h2&gt;

&lt;p&gt;Uma função normal recebe tudo pelos parâmetros:&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;func&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma closure carrega contexto junto:&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="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;

&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;offset&lt;/code&gt; não chegou por parâmetro. A função precisa lembrar dele.&lt;/p&gt;

&lt;p&gt;É como se ela carregasse uma mochila:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Closure
┌─────────────────────┐
│ código da função    │
│ contexto capturado  │
│ └── offset = 10     │
└─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso ainda não significa heap.&lt;/p&gt;

&lt;p&gt;A pergunta que decide tudo é:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Por quanto tempo esse contexto precisa existir?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Se ele morre junto com a função atual, fica na stack. Se sobrevive, vai para o heap.&lt;/p&gt;

&lt;p&gt;Quem decide isso é o &lt;strong&gt;escape analysis&lt;/strong&gt; do compilador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            captura variável
                   │
                   ▼
             ela escapa?
              /        \
            não         sim
             │           │
             ▼           ▼
           stack        heap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Então:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;capturar variável ≠ ir para o heap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos provar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provando com uma POC
&lt;/h2&gt;

&lt;p&gt;Seis cenários, do mais simples ao mais caro:&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;package&lt;/span&gt; &lt;span class="n"&gt;closurebench&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"testing"&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sinkInt&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;sinkFn&lt;/span&gt;  &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;makeAdder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// 1. função nomeada, chamada direta&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkNamedDirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sinkInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// 2. função anônima executada na hora&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkAnonymousImmediate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sinkInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// 3. closure que captura, mas não sobrevive ao loop&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkCapturedNonEscaping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;sinkInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// 4. closure criada UMA vez e reutilizada&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkClosureReused&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;makeAdder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sinkInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// 5. chamada através de um function value&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkIndirectFunctionValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sinkFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sinkInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sinkFn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// 6. closure NOVA a cada operação, que sobrevive&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkEscapingClosureCreation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sinkFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeAdder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;delta&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rodando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resultado (&lt;code&gt;go1.27.1&lt;/code&gt;, Apple M4, resumido com &lt;code&gt;benchstat&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Cenário&lt;/th&gt;
&lt;th&gt;ns/op&lt;/th&gt;
&lt;th&gt;B/op&lt;/th&gt;
&lt;th&gt;allocs/op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;nomeada direta&lt;/td&gt;
&lt;td&gt;1,614&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;anônima imediata&lt;/td&gt;
&lt;td&gt;1,614&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;closure sem escape&lt;/td&gt;
&lt;td&gt;1,889&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;closure reutilizada&lt;/td&gt;
&lt;td&gt;1,617&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;function value&lt;/td&gt;
&lt;td&gt;1,695&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;closure escapando&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5,160&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;16&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Olhe a coluna &lt;code&gt;allocs/op&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cinco zeros e um um.&lt;/p&gt;

&lt;h2&gt;
  
  
  Atenção: o número absoluto engana
&lt;/h2&gt;

&lt;p&gt;Antes de interpretar, uma armadilha que quase me pegou.&lt;/p&gt;

&lt;p&gt;Repeti a medição na mesma máquina, mesmo binário, 40 minutos depois. A única diferença: o notebook saiu da tomada e entrou em low power mode.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cenário&lt;/th&gt;
&lt;th&gt;Na tomada&lt;/th&gt;
&lt;th&gt;Na bateria&lt;/th&gt;
&lt;th&gt;Razão A&lt;/th&gt;
&lt;th&gt;Razão B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;nomeada direta&lt;/td&gt;
&lt;td&gt;1,614&lt;/td&gt;
&lt;td&gt;3,358&lt;/td&gt;
&lt;td&gt;1,00&lt;/td&gt;
&lt;td&gt;1,00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;anônima imediata&lt;/td&gt;
&lt;td&gt;1,614&lt;/td&gt;
&lt;td&gt;3,358&lt;/td&gt;
&lt;td&gt;1,00&lt;/td&gt;
&lt;td&gt;1,00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;closure sem escape&lt;/td&gt;
&lt;td&gt;1,889&lt;/td&gt;
&lt;td&gt;3,646&lt;/td&gt;
&lt;td&gt;1,17&lt;/td&gt;
&lt;td&gt;1,09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;closure reutilizada&lt;/td&gt;
&lt;td&gt;1,617&lt;/td&gt;
&lt;td&gt;3,358&lt;/td&gt;
&lt;td&gt;1,00&lt;/td&gt;
&lt;td&gt;1,00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;function value&lt;/td&gt;
&lt;td&gt;1,695&lt;/td&gt;
&lt;td&gt;3,415&lt;/td&gt;
&lt;td&gt;1,05&lt;/td&gt;
&lt;td&gt;1,02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;closure escapando&lt;/td&gt;
&lt;td&gt;5,160&lt;/td&gt;
&lt;td&gt;9,485&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3,20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2,82&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Todos os tempos dobraram.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;B/op&lt;/code&gt; e &lt;code&gt;allocs/op&lt;/code&gt; não mudaram em nenhuma linha.&lt;/p&gt;

&lt;p&gt;A regra que fica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ns/op       → depende de CPU, clock, energia, carga
              não é reproduzível

B/op        → é comportamento gerado pelo compilador
allocs/op     é reproduzível
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare razões, nunca nanossegundos.&lt;/p&gt;

&lt;h2&gt;
  
  
  A tabela não é um ranking
&lt;/h2&gt;

&lt;p&gt;Essa é a leitura errada mais fácil de fazer.&lt;/p&gt;

&lt;p&gt;Dá vontade de ordenar os seis do mais rápido ao mais lento. Mas os cinco primeiros estão empatados dentro do ruído:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────┐
│  NÃO ALOCA                      │
│                                 │
│  nomeada direta         1,00×   │
│  anônima imediata       1,00×   │
│  closure reutilizada    1,00×   │
│  function value         1,05×   │
│  closure sem escape     1,17×   │
└─────────────────────────────────┘
                 ⬇ salto
┌─────────────────────────────────┐
│  ALOCA                          │
│                                 │
│  closure escapando      3,20×   │
└─────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A separação não é gradual. É binária: &lt;strong&gt;aloca ou não aloca&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na segunda amostra, o function value caiu de 1,05× para 1,02×. A closure sem escape, de 1,17× para 1,09×.&lt;/p&gt;

&lt;p&gt;A única diferença que sobreviveu à troca de ambiente foi a alocação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provando com escape analysis
&lt;/h2&gt;

&lt;p&gt;Não precisa acreditar em mim. Pergunte ao compilador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="nt"&gt;-gcflags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'-m=2'&lt;/span&gt; ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saída do código acima inclui exatamente estas linhas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;closure_bench_test.go:14:16: makeAdder capturing by value: delta (width=8)
closure_bench_test.go:14:6:  can inline makeAdder with cost 17
closure_bench_test.go:15:9:  func literal escapes to heap     ← cenário 6
closure_bench_test.go:38:9:  func literal does not escape     ← cenário 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As duas últimas linhas são o post inteiro.&lt;/p&gt;

&lt;p&gt;Mesma sintaxe. Mesmo tipo de closure. Destinos opostos.&lt;/p&gt;

&lt;p&gt;O que muda entre elas não é como você escreveu. É se o contexto precisa sobreviver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provando com pprof
&lt;/h2&gt;

&lt;p&gt;O benchmark diz &lt;strong&gt;quanto&lt;/strong&gt;. O &lt;code&gt;pprof&lt;/code&gt; diz &lt;strong&gt;onde&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Coletando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;BenchmarkEscapingClosureCreation &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-memprofile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mem.out &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; closurebench.test

go tool pprof &lt;span class="nt"&gt;-alloc_space&lt;/span&gt; &lt;span class="nt"&gt;-top&lt;/span&gt; closurebench.test mem.out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O caminho é este:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  benchmark roda
        │
        │  -memprofile=mem.out
        ▼
┌────────────────────┐
│      mem.out       │  cada alocação + seu stack trace
└────────────────────┘
        │
        │  go tool pprof
        ▼
┌──────────────────────────────────────┐
│  -alloc_space    quantos BYTES        │  ← allocation rate
│  -alloc_objects  quantos OBJETOS      │
│  -inuse_space    o que continua VIVO  │  ← live heap
└──────────────────────────────────────┘
        │
        ▼
  linha exata do código
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guarde a diferença entre a primeira e a última flag. Vamos precisar dela daqui a pouco.&lt;/p&gt;

&lt;p&gt;A saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: alloc_space
Showing nodes accounting for 3.34GB, 99.94% of 3.34GB total

      flat  flat%        cum   cum%
    3.34GB 99.94%     3.34GB 99.94%  closurebench.makeAdder (inline)
         0     0%     3.34GB 99.94%  closurebench.BenchmarkEscapingClosureCreation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E em objetos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: alloc_objects

 224136539   100%   224136539   100%  closurebench.makeAdder (inline)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visualmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        onde alocou               quanto
┌────────────────────────────┬──────────┐
│ makeAdder (inline)         │  3.34GB  │ ████████████
│ todo o resto               │   ~2MB   │ ▏
└────────────────────────────┴──────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fecha a conta: 224.136.539 objetos × 16 B = 3,34 GB.&lt;/p&gt;

&lt;p&gt;Cem por cento da alocação em &lt;strong&gt;uma linha de código&lt;/strong&gt;, exatamente onde a closure escapa.&lt;/p&gt;

&lt;p&gt;E aqui aparece o ponto sobre frequência. Dezesseis bytes parecem irrelevantes. Multiplicados por 224 milhões, viram 3,34 GB que o allocator e o GC tiveram que processar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;custo × frequência
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se preferir navegar em vez de ler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go tool pprof &lt;span class="nt"&gt;-http&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:8080 closurebench.test mem.out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abre flame graph e visão por linha no navegador.&lt;/p&gt;

&lt;h2&gt;
  
  
  O caso que o benchmark não mostra: live heap
&lt;/h2&gt;

&lt;p&gt;Esse é o mais caro de todos. E ele não aparece em &lt;code&gt;allocs/op&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Considere:&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;func&lt;/span&gt; &lt;span class="n"&gt;firstByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&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;Agora:&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="n"&gt;buf&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="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 100 MB&lt;/span&gt;

&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;firstByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A closure usa &lt;strong&gt;1 byte&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mas ela capturou &lt;code&gt;buf&lt;/code&gt;. E o slice referencia o backing array inteiro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;closure
   │
   ▼
slice
   │
   ▼
100 MB backing array
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enquanto a closure estiver alcançável, os 100 MB também estão. O GC não pode coletar.&lt;/p&gt;

&lt;p&gt;Escrevi um teste que mede o heap vivo depois de um &lt;code&gt;runtime.GC()&lt;/code&gt;, com a closure ainda viva:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;live heap retido: 104.779.808 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cem megabytes presos por causa de um byte.&lt;/p&gt;

&lt;h3&gt;
  
  
  A correção
&lt;/h3&gt;

&lt;p&gt;Capture só o que você precisa:&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="c"&gt;// antes segura 100 MB&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;firstByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// depois segura 1 byte&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;firstByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;first&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;Mesmo teste, mesma medição:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;live heap retido: -40.160 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Negativo porque o GC ainda limpou lixo residual. Na prática: &lt;strong&gt;zero&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;E o compilador confirma:&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="n"&gt;retention_test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;19&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;29&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="n"&gt;does&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;escape&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ANTES              DEPOIS

closure            closure
   │                  │
   ▼                  ▼
slice               byte
   │
   ▼
100 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma linha de código. De 100 MB para 1 byte.&lt;/p&gt;

&lt;p&gt;É por isso que existem duas perguntas diferentes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Conceito&lt;/th&gt;
&lt;th&gt;Pergunta&lt;/th&gt;
&lt;th&gt;Flag do pprof&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Allocation rate&lt;/td&gt;
&lt;td&gt;quanta memória nova por segundo?&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-alloc_space&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live heap&lt;/td&gt;
&lt;td&gt;quanto continua alcançável?&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-inuse_space&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O benchmark só enxerga a primeira.&lt;/p&gt;

&lt;p&gt;E o caso é pior quando a closure captura algo como &lt;code&gt;req *Request&lt;/code&gt;, que referencia &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Session&lt;/code&gt;, &lt;code&gt;Headers&lt;/code&gt;, &lt;code&gt;Buffer&lt;/code&gt;, &lt;code&gt;Cache&lt;/code&gt;. Uma closure pequena mantendo um grafo inteiro vivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function value: o custo não é a chamada indireta
&lt;/h2&gt;

&lt;p&gt;Aqui eu esperava achar um vilão e não achei. Vale contar por quê.&lt;/p&gt;

&lt;p&gt;A intuição diz que isto é mais caro:&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;var&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;

&lt;span class="n"&gt;sinkInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;porque o compilador não conhece o destino direto.&lt;/p&gt;

&lt;p&gt;Medido: 1,695 contra 1,614 ns/op. Cinco por cento que viraram dois na segunda amostra.&lt;/p&gt;

&lt;p&gt;Testei também se o problema seria alvo imprevisível. Um benchmark chama sempre a mesma função; o outro alterna entre quatro:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;ns/op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;alvo sempre o mesmo&lt;/td&gt;
&lt;td&gt;1,758&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;quatro alvos em rodízio&lt;/td&gt;
&lt;td&gt;1,762&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Idênticos. A indireção em si é quase de graça em CPU moderna.&lt;/p&gt;

&lt;p&gt;O custo real é outro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function value
      ↓
compilador não sabe o destino
      ↓
não consegue inlinar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E isso só importa quando existe algo que &lt;strong&gt;valha a pena&lt;/strong&gt; inlinar.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;addOne&lt;/code&gt; é &lt;code&gt;return v + 1&lt;/code&gt;. Não há o que ganhar. Troquei por um corpo maior, um loop de oito iterações:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chamada&lt;/th&gt;
&lt;th&gt;ns/op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;direta, inlinável&lt;/td&gt;
&lt;td&gt;2,57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;via function value&lt;/td&gt;
&lt;td&gt;3,51&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Agora sim: &lt;strong&gt;36% a mais&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ou seja:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;named function    ≠ automaticamente rápida
anonymous function ≠ automaticamente lenta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que importa é o que o compilador conseguiu gerar e o que ele deixou de conseguir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regra de ouro
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Não otimize a sintaxe. Otimize o comportamento gerado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Na prática, isso vira três perguntas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A closure &lt;strong&gt;escapa&lt;/strong&gt;? (escape analysis responde)&lt;/li&gt;
&lt;li&gt;Ela &lt;strong&gt;aloca&lt;/strong&gt; por operação? (benchmark responde)&lt;/li&gt;
&lt;li&gt;Ela &lt;strong&gt;segura&lt;/strong&gt; algo grande vivo? (&lt;code&gt;-inuse_space&lt;/code&gt; responde)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Se as três respostas forem não, não existe otimização a fazer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como investigar, na ordem certa
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Benchmark
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Máquina ociosa e na tomada. Já mostrei o que acontece quando não é.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Escape analysis
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="nt"&gt;-gcflags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'-m=2'&lt;/span&gt; ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Procure por &lt;code&gt;escapes to heap&lt;/code&gt;, &lt;code&gt;does not escape&lt;/code&gt;, &lt;code&gt;capturing by value&lt;/code&gt;, &lt;code&gt;can inline&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Memory profile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-memprofile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mem.out
go tool pprof &lt;span class="nt"&gt;-alloc_space&lt;/span&gt; mem.out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde estou alocando, em vez de onde eu acho que estou.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Compare antes e depois
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; before.txt
&lt;span class="c"&gt;# ... sua mudança ...&lt;/span&gt;
go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-bench&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; after.txt

benchstat before.txt after.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;benchstat&lt;/code&gt; diz se a diferença é sinal ou ruído. Uma execução única não diz nada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use função anônima sem medo aqui
&lt;/h2&gt;

&lt;p&gt;Callbacks:&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="n"&gt;slices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SortFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cmp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&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;Handlers:&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="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&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;Goroutines:&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;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;process&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;Defer:&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;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cleanup&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;Nesses casos você ganha localidade, legibilidade e encapsulamento. E, pelos números acima, não paga nada por isso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Investigue quando aparecerem juntos
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;closure + hot path + alta frequência + allocation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemplo clássico:&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;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;item&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;millionsOfItems&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;createProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c"&gt;// closure nova a cada item&lt;/span&gt;

    &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c"&gt;// e todas sobrevivem&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou closures guardadas por muito tempo em slice, map, queue, channel ou variável global.&lt;/p&gt;

&lt;p&gt;E, principalmente: closures que capturam estruturas grandes.&lt;/p&gt;

&lt;h2&gt;
  
  
  E aumentar o GOGC resolve?
&lt;/h2&gt;

&lt;p&gt;Não.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GOGC maior              GOGC menor
    ↓                       ↓
GC menos frequente      GC mais frequente
mais memória            menos memória
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É uma troca entre CPU e memória. É runtime tuning.&lt;/p&gt;

&lt;p&gt;Não remove uma allocation desnecessária de um hot path.&lt;/p&gt;

&lt;h2&gt;
  
  
  E zerar todas as allocations?
&lt;/h2&gt;

&lt;p&gt;Também não.&lt;/p&gt;

&lt;p&gt;Uma operação que roda 10 vezes por minuto: 1 alloc/op não importa.&lt;/p&gt;

&lt;p&gt;A mesma operação 5 milhões de vezes por segundo: muda tudo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Performance precisa de contexto.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Comparativo final
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situação&lt;/th&gt;
&lt;th&gt;Preocupa?&lt;/th&gt;
&lt;th&gt;Medido&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Função anônima simples&lt;/td&gt;
&lt;td&gt;não&lt;/td&gt;
&lt;td&gt;idêntico à nomeada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closure com 0 allocs/op&lt;/td&gt;
&lt;td&gt;não&lt;/td&gt;
&lt;td&gt;1,00–1,17×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closure criada uma vez e reutilizada&lt;/td&gt;
&lt;td&gt;não&lt;/td&gt;
&lt;td&gt;1,00×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function value em hot path&lt;/td&gt;
&lt;td&gt;só se a função for grande&lt;/td&gt;
&lt;td&gt;1,05× aqui, 1,36× com corpo maior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closure escapando a cada operação&lt;/td&gt;
&lt;td&gt;sim&lt;/td&gt;
&lt;td&gt;3,20× + 16 B/op&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closure capturando objeto grande&lt;/td&gt;
&lt;td&gt;sim&lt;/td&gt;
&lt;td&gt;100 MB retidos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Milhões de allocations por segundo&lt;/td&gt;
&lt;td&gt;atenção alta&lt;/td&gt;
&lt;td&gt;3,34 GB no profile&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Existe closure?
      ↓
Captura variável?
      ↓
Escapa? ............. gcflags=-m=2
      ↓
Aloca por operação? . benchmark
      ↓
Está em hot path?
      ↓
Aparece no profile? . pprof
      ↓
Só então otimizar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se travou em qualquer etapa, pare. Não tem otimização ali.&lt;/p&gt;

&lt;h2&gt;
  
  
  Código da POC
&lt;/h2&gt;

&lt;p&gt;Os 6 benchmarks, os testes que transformam a tabela em asserção, o teste de live heap e o script que roda benchmark + escape analysis + &lt;code&gt;pprof&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;REPO&amp;gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;PASTA&amp;gt;
./run.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os seus números vão ser diferentes dos meus. Compare as &lt;strong&gt;razões&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;E se você achar um cenário que contradiz algum destes resultados, me manda nos comentários, eu rodo.&lt;/p&gt;

</description>
      <category>go</category>
      <category>performance</category>
      <category>benchmark</category>
      <category>garbagecollector</category>
    </item>
    <item>
      <title>Seu servidor pode estar confiando em certificados falsos. Veja como testar e corrigir.</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Tue, 03 Nov 2026 17:37:48 +0000</pubDate>
      <link>https://dev.to/renanbastos93/seu-servidor-pode-estar-confiando-em-certificados-falsos-veja-como-testar-e-corrigir-57lc</link>
      <guid>https://dev.to/renanbastos93/seu-servidor-pode-estar-confiando-em-certificados-falsos-veja-como-testar-e-corrigir-57lc</guid>
      <description>&lt;h2&gt;
  
  
  Seu servidor pode estar confiando em certificados falsos. Veja como testar.
&lt;/h2&gt;

&lt;p&gt;Imagine receber uma ligação de alguém que se apresenta como funcionário do seu banco. A pessoa conhece os procedimentos, passa informações convincentes e parece legítima.&lt;/p&gt;

&lt;p&gt;Mas é um golpista.&lt;/p&gt;

&lt;p&gt;Na internet, algo parecido pode acontecer com os certificados digitais. Eles ajudam seu computador a verificar se um site é realmente quem diz ser.&lt;/p&gt;

&lt;p&gt;Foi justamente esse mecanismo de confiança que entrou em risco com o incidente da &lt;strong&gt;eMudhra (emSign)&lt;/strong&gt;, divulgado em outubro de 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que aconteceu?
&lt;/h2&gt;

&lt;p&gt;As chaves privadas de oito certificados intermediários da eMudhra foram comprometidas.&lt;/p&gt;

&lt;p&gt;Com essas chaves, um atacante poderia criar certificados aparentemente legítimos para domínios que não controla.&lt;/p&gt;

&lt;p&gt;Na prática, isso abre espaço para ataques de &lt;em&gt;man-in-the-middle&lt;/em&gt; (MITM), nos quais um criminoso intercepta a comunicação entre você e um serviço.&lt;/p&gt;

&lt;p&gt;Isso não significa que seu servidor foi invadido. Significa que ele pode estar confiando em certificados que não deveria.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A solução é atualizar os certificados de confiança e verificar se o sistema passou a rejeitar os comprometidos.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Como saber se você está vulnerável?
&lt;/h2&gt;

&lt;p&gt;Os pesquisadores disponibilizaram um endereço para testar essa falha.&lt;/p&gt;

&lt;p&gt;No Linux ou macOS, execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://dv-g3b-emudhra.we-have-a-problem.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se aparecer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your client successfully connected to the site.
That's bad!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Seu &lt;code&gt;curl&lt;/code&gt; aceitou a cadeia comprometida.&lt;/strong&gt; É necessário corrigir.&lt;/p&gt;

&lt;p&gt;O resultado esperado em um ambiente corrigido é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (60) SSL certificate problem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse erro é uma boa notícia: significa que o certificado foi rejeitado.&lt;/p&gt;

&lt;p&gt;Erros de DNS ou timeout não comprovam que o sistema está protegido.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Como corrigir no Linux
&lt;/h2&gt;

&lt;p&gt;Primeiro, descubra qual distribuição está utilizando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/os-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para identificar a arquitetura do processador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;x86_64&lt;/code&gt;: normalmente Intel ou AMD.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aarch64&lt;/code&gt;: arquitetura ARM64, como a Orange Pi.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ubuntu e Debian
&lt;/h3&gt;

&lt;p&gt;Descubra a versão instalada dos certificados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dpkg-query &lt;span class="nt"&gt;-W&lt;/span&gt; ca-certificates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confira qual versão está disponível para atualização:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt-cache policy ca-certificates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora atualize:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--only-upgrade&lt;/span&gt; ca-certificates
&lt;span class="nb"&gt;sudo &lt;/span&gt;update-ca-certificates &lt;span class="nt"&gt;--fresh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Algumas versões corrigidas de referência:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Distribuição&lt;/th&gt;
&lt;th&gt;Versão corrigida&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu 22.04&lt;/td&gt;
&lt;td&gt;&lt;code&gt;20260816ubuntu0.22.04.1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu 24.04&lt;/td&gt;
&lt;td&gt;&lt;code&gt;20260816ubuntu0.24.04.1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debian 12&lt;/td&gt;
&lt;td&gt;&lt;code&gt;20250419~deb12u2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debian 13&lt;/td&gt;
&lt;td&gt;&lt;code&gt;20250419+deb13u1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Se o sistema não oferecer uma versão corrigida, revise os repositórios de segurança antes de prosseguir.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Como corrigir no macOS
&lt;/h2&gt;

&lt;p&gt;No macOS, existe um detalhe: o &lt;code&gt;curl&lt;/code&gt; nativo da Apple pode utilizar certificados diferentes dos utilizados pelo Homebrew.&lt;/p&gt;

&lt;p&gt;Descubra qual versão está sendo executada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;which curl
curl &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se aparecer &lt;code&gt;/usr/bin/curl&lt;/code&gt;, você está utilizando a versão fornecida pela Apple.&lt;/p&gt;

&lt;p&gt;Uma alternativa é instalar e atualizar o &lt;code&gt;curl&lt;/code&gt; pelo Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew update
brew &lt;span class="nb"&gt;install &lt;/span&gt;ca-certificates curl
brew upgrade ca-certificates curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois, configure o terminal para priorizá-lo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$(brew --prefix)/opt/curl/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;which curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O caminho deve apontar para o Homebrew, não para &lt;code&gt;/usr/bin/curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importante:&lt;/strong&gt; isso não corrige automaticamente o &lt;code&gt;curl&lt;/code&gt; nativo da Apple nem outros aplicativos. Eles precisam ser verificados separadamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Como validar a correção
&lt;/h2&gt;

&lt;p&gt;Execute os dois testes disponibilizados pelos pesquisadores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;domain &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  dv-g3b-emudhra.we-have-a-problem.com &lt;span class="se"&gt;\&lt;/span&gt;
  dv-g3b-aaa-emudhra.we-have-a-problem.com
&lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Testando: &lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  curl &lt;span class="nt"&gt;--noproxy&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--connect-timeout&lt;/span&gt; 10 &lt;span class="nt"&gt;--max-time&lt;/span&gt; 20 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'HTTP: %{http_code} | Verify: %{ssl_verify_result}\n'&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado esperado para ambos é semelhante a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (60) SSL certificate problem
HTTP: 000 | Verify: 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora confirme que uma conexão HTTPS legítima continua funcionando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma resposta como &lt;code&gt;HTTP/2 200&lt;/code&gt; confirma que o &lt;code&gt;curl&lt;/code&gt; conseguiu estabelecer essa conexão normalmente.&lt;/p&gt;

&lt;p&gt;Não utilize &lt;code&gt;curl -k&lt;/code&gt; ou &lt;code&gt;--insecure&lt;/code&gt;, porque esses parâmetros desabilitam justamente a validação que queremos testar.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. E os serviços em Docker, Go, Python e Node.js?
&lt;/h2&gt;

&lt;p&gt;Aqui está um detalhe importante: &lt;strong&gt;atualizar o sistema operacional não garante que todas as aplicações estejam corrigidas.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Algumas utilizam bibliotecas ou certificados próprios.&lt;/p&gt;

&lt;p&gt;Versões corrigidas de referência:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tecnologia&lt;/th&gt;
&lt;th&gt;Versão&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;1.26.10 ou 1.27.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python (&lt;code&gt;certifi&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;2026.10.19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js 22&lt;/td&gt;
&lt;td&gt;22.23.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js 24&lt;/td&gt;
&lt;td&gt;24.22.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js 26&lt;/td&gt;
&lt;td&gt;26.12.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Para verificar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go version
node &lt;span class="nt"&gt;-v&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip show certifi
docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se estiver utilizando Docker, revise também as imagens-base e os certificados de cada contêiner.&lt;/p&gt;

&lt;p&gt;No Go, atualizar a versão instalada não corrige automaticamente os binários já compilados: é necessário recompilá-los com a versão corrigida.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. O que encontrei nos meus servidores?
&lt;/h2&gt;

&lt;p&gt;Depois de receber o alerta, resolvi verificar três ambientes que utilizo:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ambiente&lt;/th&gt;
&lt;th&gt;Resultado&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Orange Pi 5 Max (Ubuntu)&lt;/td&gt;
&lt;td&gt;Vulnerável inicialmente; corrigida&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPS Hostinger (Debian)&lt;/td&gt;
&lt;td&gt;Vulnerável inicialmente; corrigida&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPS Contabo (Ubuntu)&lt;/td&gt;
&lt;td&gt;Já rejeitava os certificados comprometidos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Os três passaram nos testes finais do &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O mais interessante é que os servidores estavam funcionando normalmente. Nenhuma falha aparente, nenhum serviço necessariamente parado.&lt;/p&gt;

&lt;p&gt;O problema estava na confiança depositada em certificados comprometidos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Um serviço estar online não significa necessariamente que está seguro.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Segurança não é apenas manter sistemas atualizados. É também testar se as correções realmente funcionaram.&lt;/p&gt;

&lt;p&gt;Nesse caso, alguns comandos foram suficientes para encontrar um problema real, aplicar a correção e validar o resultado.&lt;/p&gt;

&lt;p&gt;Vale lembrar que os testes apresentados verificam o comportamento do &lt;code&gt;curl&lt;/code&gt;. Aplicações com mecanismos próprios de validação TLS precisam ser avaliadas separadamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agradecimentos
&lt;/h2&gt;

&lt;p&gt;Esse artigo nasceu de um alerta compartilhado no Slack pelo meu colega &lt;strong&gt;&lt;a href="https://www.linkedin.com/in/jefferson-luis-martins/" rel="noopener noreferrer"&gt;Jefferson Luis Martins (Jeff)&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ele trouxe o contexto do incidente, explicou os riscos e compartilhou orientações para correção, o que me motivou a verificar meus próprios ambientes.&lt;/p&gt;

&lt;p&gt;Valeu pelo alerta, Jeff!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Segurança também se constrói compartilhando conhecimento.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://emudhra.we-have-a-problem.com/" rel="noopener noreferrer"&gt;Relatório técnico do incidente eMudhra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://curl.se/docs/sslcerts.html" rel="noopener noreferrer"&gt;Documentação do curl sobre certificados SSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ubuntu.com/security" rel="noopener noreferrer"&gt;Ubuntu Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.debian.org/security/" rel="noopener noreferrer"&gt;Debian Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Publicado em outubro de 2026. As versões e recomendações refletem as informações disponíveis na data da publicação.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>linux</category>
      <category>devops</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>The Rise of Solution Architects in the Age of Artificial Intelligence</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Fri, 24 Apr 2026 02:01:41 +0000</pubDate>
      <link>https://dev.to/renanbastos93/the-rise-of-solution-architects-in-the-age-of-artificial-intelligence-824</link>
      <guid>https://dev.to/renanbastos93/the-rise-of-solution-architects-in-the-age-of-artificial-intelligence-824</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Based on what I have observed in the technology market, a clear and inevitable shift is taking place. This perspective comes not only from global trends but also from my daily experience building scalable solutions and working with Artificial Intelligence.&lt;/p&gt;

&lt;p&gt;We are entering a new era where AI is no longer just a support tool—it is becoming a strategic ally in building products and services. In this scenario, the role of the Solution Architect is gaining prominence, connecting technology, business strategy, and real-world outcomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Code Executors to Solution Engineers
&lt;/h2&gt;

&lt;p&gt;With the rapid advancement of AI, the demand for developers focused solely on task execution is decreasing. This does not mean the end of software development—it means evolution.&lt;/p&gt;

&lt;p&gt;Professionals who limit themselves to coding without understanding business context risk being replaced by automation. Meanwhile, the demand for Solution Engineers and Architects continues to grow.&lt;/p&gt;

&lt;p&gt;These professionals are expected to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand business rules and strategic goals&lt;/li&gt;
&lt;li&gt;Translate requirements into scalable solutions&lt;/li&gt;
&lt;li&gt;Leverage AI to enhance productivity&lt;/li&gt;
&lt;li&gt;Orchestrate complex systems&lt;/li&gt;
&lt;li&gt;Deliver measurable business impact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technical expertise remains essential, but strategic thinking has become the true differentiator.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rise of AI Agents and Intelligent Orchestration
&lt;/h2&gt;

&lt;p&gt;As AI ecosystems evolve, new tools are emerging to manage, govern, and scale intelligent systems. One such concept is the &lt;strong&gt;Harness&lt;/strong&gt;, which represents the ability to orchestrate resources, configure memory, and ensure governance in AI-driven environments.&lt;/p&gt;

&lt;p&gt;Rather than being just a tool, Harness embodies a new paradigm in software development, enabling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI agent orchestration&lt;/li&gt;
&lt;li&gt;Memory configuration and management&lt;/li&gt;
&lt;li&gt;Governance and observability&lt;/li&gt;
&lt;li&gt;Seamless integrations&lt;/li&gt;
&lt;li&gt;Security and operational control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach allows organizations to build robust, scalable, and business-aligned solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business Impact
&lt;/h2&gt;

&lt;p&gt;For companies, this transformation is more than technological—it is strategic. Organizations that adopt AI with governance and vision can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increase operational efficiency&lt;/li&gt;
&lt;li&gt;Reduce costs&lt;/li&gt;
&lt;li&gt;Scale faster&lt;/li&gt;
&lt;li&gt;Improve decision-making&lt;/li&gt;
&lt;li&gt;Drive innovation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technology is no longer just a support function—it is a core driver of business value.&lt;/p&gt;

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

&lt;p&gt;In my view, the market is evolving at an unprecedented pace. The future belongs not only to those who can code, but to those who understand business and leverage technology strategically.&lt;/p&gt;

&lt;p&gt;We are witnessing the rise of a new generation of professionals—Solution Engineers and Architects—who will orchestrate innovation with the support of Artificial Intelligence.&lt;/p&gt;

&lt;p&gt;Tools like Harness symbolize this new era, where intelligence lies not only in code, but in the ability to connect technology, governance, and strategy.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>solutionarchitecture</category>
      <category>engineering</category>
      <category>futureofwork</category>
    </item>
    <item>
      <title>Seu app Go no K8s está usando até 20x mais CPU do que deveria (e como corrigir do jeito certo)</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Fri, 27 Feb 2026 01:09:31 +0000</pubDate>
      <link>https://dev.to/renanbastos93/seu-app-go-no-k8s-esta-usando-ate-20x-mais-cpu-do-que-deveria-e-como-corrigir-do-jeito-certo-3g15</link>
      <guid>https://dev.to/renanbastos93/seu-app-go-no-k8s-esta-usando-ate-20x-mais-cpu-do-que-deveria-e-como-corrigir-do-jeito-certo-3g15</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Esse é um bug &lt;strong&gt;extremamente comum&lt;/strong&gt; em aplicações Go rodando em Kubernetes — inclusive em times experientes.&lt;/p&gt;

&lt;p&gt;Os sintomas quase sempre são os mesmos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU alta mesmo com pouco tráfego&lt;/li&gt;
&lt;li&gt;latência instável&lt;/li&gt;
&lt;li&gt;throttling frequente no pod&lt;/li&gt;
&lt;li&gt;autoscaling agressivo sem ganho real de throughput&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na maioria dos casos, o culpado é este aqui:&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="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste post você vai entender:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Por que &lt;code&gt;NumCPU()&lt;/code&gt; é errado em containers&lt;/li&gt;
&lt;li&gt;Como o Kubernetes realmente limita CPU&lt;/li&gt;
&lt;li&gt;A solução correta (com e sem &lt;code&gt;automaxprocs&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Qual é a boa prática de pool size por core&lt;/li&gt;
&lt;li&gt;Quantas goroutines por core fazem sentido na prática&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;Muitas libs Go dimensionam concorrência com base em &lt;code&gt;runtime.NumCPU()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;worker pools&lt;/li&gt;
&lt;li&gt;connection pools&lt;/li&gt;
&lt;li&gt;filas&lt;/li&gt;
&lt;li&gt;paralelismo interno&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplo real:&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="n"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso parece razoável fora de containers.&lt;/p&gt;

&lt;p&gt;Mas dentro do Kubernetes, isso é um erro sério.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que runtime.NumCPU() realmente retorna
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;runtime.NumCPU()&lt;/code&gt; não lê o cgroup.&lt;/p&gt;

&lt;p&gt;Ele retorna os CPUs visíveis do host, não o limite do container.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node com 64 CPUs&lt;/li&gt;
&lt;li&gt;Pod com resources.limits.cpu: 500m&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;runtime.NumCPU() = 64
poolSize = 640 goroutines
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seu pod tem meio core e está tentando rodar 640 goroutines concorrentes.&lt;/p&gt;

&lt;p&gt;Resultado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;context switch excessivo&lt;/li&gt;
&lt;li&gt;CPU throttling constante&lt;/li&gt;
&lt;li&gt;latência imprevisível&lt;/li&gt;
&lt;li&gt;performance pior&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Como o Kubernetes limita CPU
&lt;/h2&gt;

&lt;p&gt;Quando você define:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;500m"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Kubernetes configura o cgroup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/sys/fs/cgroup/cpu.max = 50000 100000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso significa 0.5 CPU.&lt;/p&gt;

&lt;p&gt;O Go runtime não considera isso ao usar NumCPU().&lt;/p&gt;

&lt;h2&gt;
  
  
  Provando com uma POC
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"runtime"&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"go.uber.org/automaxprocs"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NumCPU()      = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GOMAXPROCS(0) = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&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;Rodando com Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --cpus=0.5 → NumCPU=10  GOMAXPROCS=1
docker run --cpus=1   → NumCPU=10  GOMAXPROCS=1
docker run --cpus=2   → NumCPU=10  GOMAXPROCS=2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conclusão:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NumCPU() sempre retorna o host&lt;/li&gt;
&lt;li&gt;GOMAXPROCS respeita o limit quando configurado corretamente&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Regra de ouro
&lt;/h2&gt;

&lt;p&gt;Nunca use runtime.NumCPU() para dimensionar concorrência em containers.&lt;/p&gt;

&lt;p&gt;Sempre use runtime.GOMAXPROCS(0).&lt;/p&gt;

&lt;h2&gt;
  
  
  A solução correta
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// errado&lt;/span&gt;
&lt;span class="n"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;// correto&lt;/span&gt;
&lt;span class="n"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Go ≤ 1.24 vs Go ≥ 1.25
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Go 1.24 e abaixo
&lt;/h3&gt;

&lt;p&gt;Até o Go 1.24, o runtime não era container-aware.&lt;/p&gt;

&lt;p&gt;É obrigatório usar:&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;import&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"go.uber.org/automaxprocs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Go 1.25+
&lt;/h3&gt;

&lt;p&gt;A partir do Go 1.25:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;o runtime já lê o cgroup&lt;/li&gt;
&lt;li&gt;GOMAXPROCS é ajustado automaticamente&lt;/li&gt;
&lt;li&gt;não precisa mais do automaxprocs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quantas goroutines por core?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CPU-bound
&lt;/h3&gt;

&lt;p&gt;Regra:&lt;/p&gt;

&lt;p&gt;1 goroutine por core&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="n"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  I/O-bound
&lt;/h3&gt;

&lt;p&gt;Boa prática:&lt;/p&gt;

&lt;p&gt;5 a 10 goroutines por core&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="n"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No máximo:&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="n"&gt;poolSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pools de conexão
&lt;/h3&gt;

&lt;p&gt;Boa prática:&lt;/p&gt;

&lt;p&gt;2 a 4 conexões por core&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="n"&gt;maxConns&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comparativo
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CPU limit&lt;/th&gt;
&lt;th&gt;NumCPU()&lt;/th&gt;
&lt;th&gt;GOMAXPROCS&lt;/th&gt;
&lt;th&gt;Pool recomendado&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;500m&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5–10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000m&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5–10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2000m&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;10–20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nunca use runtime.NumCPU() em containers&lt;/li&gt;
&lt;li&gt;Sempre use runtime.GOMAXPROCS(0)&lt;/li&gt;
&lt;li&gt;Go ≤ 1.24 → use automaxprocs&lt;/li&gt;
&lt;li&gt;Go ≥ 1.25 → não precisa&lt;/li&gt;
&lt;li&gt;CPU-bound → 1 goroutine por core&lt;/li&gt;
&lt;li&gt;I/O-bound → 5–10 goroutines por core&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Código da POC
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/renanbastos93/numcpu-k8s" rel="noopener noreferrer"&gt;https://github.com/renanbastos93/numcpu-k8s&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>kubernetes</category>
      <category>cpu</category>
      <category>performance</category>
    </item>
    <item>
      <title>Pipeline em Go - Compondo operações de forma elegante e simples</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Fri, 10 Oct 2025 02:33:47 +0000</pubDate>
      <link>https://dev.to/renanbastos93/pipeline-em-go-compondo-operacoes-de-forma-elegante-e-simples-16p3</link>
      <guid>https://dev.to/renanbastos93/pipeline-em-go-compondo-operacoes-de-forma-elegante-e-simples-16p3</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Recentemente embarcamos em um pequeno projeto interno com o colega &lt;a href="https://www.linkedin.com/in/jonassfreire/" rel="noopener noreferrer"&gt;Jonas Freire&lt;/a&gt;: criar uma forma mais expressiva e limpa de encadear operações em Go. Eu participei ajudando a definir contratos, escrever testes e validar o comportamento do pacote. Em conjunto com a empresa, decidimos abrir esse trabalho como &lt;em&gt;open source&lt;/em&gt;, para que outros desenvolvedores também possam usar, contribuir e nos dar feedback.&lt;/p&gt;

&lt;p&gt;Esse artigo vai mostrar, de forma simples e prática, &lt;strong&gt;como usar o pacote&lt;/strong&gt; &lt;a href="https://github.com/lastro-co/pipeline" rel="noopener noreferrer"&gt;pipeline&lt;/a&gt;, seus conceitos básicos e alguns exemplos reais para você começar rapidamente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Por que usar pipeline?
&lt;/h2&gt;

&lt;p&gt;Em Go, quando você precisa realizar várias transformações ou validações consecutivas, o código costuma ficar assim:&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="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;foo&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou, se for uma cadeia de funções, você acaba fazendo algo como:&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="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fn3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso torna o fluxo difícil de ler e difícil de inserir tratamento de erro de forma padronizada.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;pipeline&lt;/strong&gt; deste projeto provê um jeito idiomático de criar uma sequência de operações que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recebe um valor inicial&lt;/li&gt;
&lt;li&gt;Aplica passos (funções) um após o outro&lt;/li&gt;
&lt;li&gt;Interrompe a execução no primeiro erro&lt;/li&gt;
&lt;li&gt;Retorna o valor final ou o erro ocorrido&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ou seja: deixa o encadeamento linear, evita repetição de checagem de erro e melhora a legibilidade.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conceitos principais
&lt;/h2&gt;

&lt;p&gt;Aqui estão os conceitos centrais que você precisa entender para usar o pipeline:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Conceito&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Step[T]&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;É um tipo de função que representa um passo da pipeline: &lt;code&gt;func(ctx context.Context, T) (T, error)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pipeline[T]&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;O construtor da sequência de passos, começando com um valor inicial de tipo &lt;code&gt;T&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New(initial T)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cria uma nova pipeline com valor inicial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Do(step Step[T])&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Adiciona mais um passo à pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execute() / ExecuteWithContext(ctx)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Executa todos os passos até o fim ou até encontrar erro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ToStep(...)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Função auxiliar que converte funções “normais” (por exemplo &lt;code&gt;func(T) T&lt;/code&gt; ou &lt;code&gt;func(T) (T, error)&lt;/code&gt;) para o formato &lt;code&gt;Step[T]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O pipeline também incorpora suporte a contexto, para cancelamento ou timeout, e retorna erros enriquecidos com informações como em que passo ocorreu a falha.&lt;/p&gt;




&lt;h2&gt;
  
  
  Como usar (exemplos práticos)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Exemplo básico com strings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"strings"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/lastro-co/pipeline"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ensureNonEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&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;error&lt;/span&gt;&lt;span class="p"&gt;)&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;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"string vazia"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  ola mundo  "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimSpace&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;   &lt;span class="c"&gt;// converte func(string) string&lt;/span&gt;
        &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToUpper&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;     &lt;span class="c"&gt;// outra função simples&lt;/span&gt;
        &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ensureNonEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;                       &lt;span class="c"&gt;// função já no formato Step[T]&lt;/span&gt;
        &lt;span class="n"&gt;Execute&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Erro:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Resultado:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&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;Aqui estamos compondo 3 passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;TrimSpace&lt;/code&gt; para remover espaços&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ToUpper&lt;/code&gt; para deixar em maiúsculo&lt;/li&gt;
&lt;li&gt;Validar que não ficou vazio&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Se em algum passo houver erro (por exemplo valor vazio), a execução para ali e retorna o erro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adaptando funções com múltiplos parâmetros
&lt;/h3&gt;

&lt;p&gt;Se você já tiver uma função como:&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;func&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode adaptá-la dentro da pipeline usando uma &lt;em&gt;closure&lt;/em&gt;:&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim você encapsula a lógica e transforma em um &lt;code&gt;Step[int]&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uso de contexto / timeout
&lt;/h3&gt;

&lt;p&gt;Você pode usar &lt;code&gt;ExecuteWithContext&lt;/code&gt; para que a pipeline respeite cancelamento ou timeout:&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="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"algum valor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToUpper&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slowStep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;   &lt;span class="c"&gt;// passo que demora&lt;/span&gt;
    &lt;span class="n"&gt;ExecuteWithContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Por exemplo: context.DeadlineExceeded&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Falha:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;Se o contexto for encerrado antes do término, o pipeline interrompe e retorna o erro do contexto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Erros com contexto de passo
&lt;/h3&gt;

&lt;p&gt;Quando um passo falha, o pacote retorna um erro enriquecido (&lt;code&gt;PipelineError&lt;/code&gt;) que contém:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;StepIndex&lt;/code&gt;: índice do passo que falhou&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TotalSteps&lt;/code&gt;: número total de passos&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OriginalErr&lt;/code&gt;: o erro retornado pela função que falhou&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LastValue&lt;/code&gt;: último valor processado até então&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso ajuda a depurar exatamente onde a falha ocorreu.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dicas boas práticas &amp;amp; considerações
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prefira criar passos pequenos, com responsabilidade única.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;ToStep(...)&lt;/code&gt; sempre que possível para converter funções existentes e evitar boilerplate.&lt;/li&gt;
&lt;li&gt;Teste cada passo isoladamente para garantir que o comportamento de erro está correto.&lt;/li&gt;
&lt;li&gt;Para operações que recebem múltiplos parâmetros, use closures como mostrado acima.&lt;/li&gt;
&lt;li&gt;Em casos especiais, você pode usar tipos de erro customizados para identificar falhas específicas e tratá-las de forma distinta após &lt;code&gt;Execute&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusão e convite à comunidade
&lt;/h2&gt;

&lt;p&gt;Esse pacote surgiu como uma iniciativa interna do Jonas (e com minha ajuda nos contratos e testes) e agora está aberto como open source. A ideia é oferecer uma forma elegante e clara de encadear operações em Go, com tratamento automático de erros e suporte a contexto.&lt;/p&gt;

&lt;p&gt;Se você gostou e quiser contribuir — seja com sugestões, documentação, exemplos ou novos recursos — fique à vontade para abrir issues, pull requests ou me chamar. Vamos crescer juntos! 🚀&lt;/p&gt;

</description>
      <category>go</category>
      <category>opensource</category>
      <category>cleancode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Por que você deve repensar o uso de Regex em validações de strings em Go</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Sun, 23 Feb 2025 00:05:15 +0000</pubDate>
      <link>https://dev.to/renanbastos93/por-que-voce-deve-repensar-o-uso-de-regex-em-validacoes-de-strings-no-go-1cdi</link>
      <guid>https://dev.to/renanbastos93/por-que-voce-deve-repensar-o-uso-de-regex-em-validacoes-de-strings-no-go-1cdi</guid>
      <description>&lt;p&gt;Quando falamos de validação de strings no Go, uma das soluções mais comuns é o uso de expressões regulares (regex). No entanto, dependendo do contexto, o uso de regex pode ser menos eficiente do que alternativas mais simples. Em sistemas de alta performance, como os que lidam com grandes volumes de dados ou que precisam ser executados em ambientes com recursos limitados, é importante considerar o impacto de cada escolha de implementação.&lt;/p&gt;

&lt;p&gt;Embora regex seja uma ferramenta poderosa, sua utilização indiscriminada pode resultar em impactos de performance, principalmente em Go, onde cada operação é otimizada ao máximo para garantir alta eficiência. Neste post, vamos abordar um exemplo simples de validação de strings alfanuméricas, comparando o uso de regex com uma abordagem baseada em Unicode e explicando como otimizar o uso de regex no Go para obter melhores resultados.&lt;/p&gt;

&lt;p&gt;O que acontece por trás das cortinas: Regex vs Unicode&lt;br&gt;
A biblioteca &lt;code&gt;regexp&lt;/code&gt; é bastante útil, mas pode ser mais lenta do que validações feitas manualmente usando funções da biblioteca unicode. Isso ocorre porque o Go precisa compilar o regex e avaliar sua expressão toda vez que é usado dentro de um método. Isso consome mais tempo de CPU e memória, especialmente em validações simples, como a checagem, se uma string contém apenas caracteres alfanuméricos.&lt;/p&gt;

&lt;p&gt;A alternativa, mais eficiente, é iterar sobre a string e validar cada caractere individualmente, utilizando funções como unicode.IsLetter e unicode.IsDigit. Isso evita a sobrecarga de compilar o regex toda vez que a função é chamada e pode ser muito mais rápido para cenários simples.&lt;/p&gt;
&lt;h2&gt;
  
  
  Exemplo prático: Comparando as abordagens
&lt;/h2&gt;

&lt;p&gt;Aqui está um exemplo em Go para comparar as duas abordagens: uma usando regex e outra utilizando Unicode diretamente.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementação com Regex:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustCompile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`^[A-Za-z0-9_]+$`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;isValidWithRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;h3&gt;
  
  
  Implementação usando Unicode:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;bool&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;r&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;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unicode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsLetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;unicode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDigit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="c"&gt;// Garante que a string não está vazia&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Comparação de Performance
&lt;/h2&gt;

&lt;p&gt;Vamos rodar alguns benchmarks para comparar a performance das duas abordagens.&lt;/p&gt;
&lt;h3&gt;
  
  
  Benchmark com Unicode:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// BenchmarkTestIsValid-8       18216368            66.18 ns/op        0 B/op          0 allocs/op&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkTestIsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Teste_123"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valido_ABC"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalido!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"12345"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&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;h3&gt;
  
  
  Benchmark com Regex:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// BenchmarkTestIsValidWithRegex-8       3069778           401.3 ns/op         0 B/op          0 allocs/op&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkTestIsValidWithRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&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;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Teste_123"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valido_ABC"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"12345"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&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;h2&gt;
  
  
  Resultados
&lt;/h2&gt;

&lt;p&gt;Como você pode observar nos benchmarks acima, a versão que usa Unicode é significativamente mais rápida do que a versão com regex. A versão com Unicode realiza cerca de 18 milhões de operações por segundo, enquanto a versão com regex realiza apenas cerca de 3 milhões.&lt;/p&gt;
&lt;h3&gt;
  
  
  Por que isso acontece?
&lt;/h3&gt;

&lt;p&gt;Quando usamos regex, estamos criando e compilando uma expressão regular toda vez que chamamos a função. O processo de compilação e execução da expressão regular envolve mais passos do que simplesmente iterar sobre os caracteres da string com funções do unicode. Isso faz com que a execução com regex consuma mais tempo de CPU e memória.&lt;/p&gt;
&lt;h3&gt;
  
  
  Quando usar Regex?
&lt;/h3&gt;

&lt;p&gt;Isso não significa que você deve parar de usar regex. Em casos mais complexos, onde você precisa de validações mais sofisticadas, regex pode ser a melhor escolha. No entanto, em validações simples, como a checagem de caracteres alfanuméricos, o uso de Unicode diretamente é muito mais eficiente.&lt;/p&gt;

&lt;p&gt;Dica de Performance: Compile Regex fora do método&lt;br&gt;
Se você optar por usar regex, uma boa prática é compilar a expressão regular fora do método, para que ela não precise ser recompilada a cada chamada. Isso pode ajudar a reduzir o custo de performance de usar regex.&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;var&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MustCompile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`^[A-Za-z0-9_]+$`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;isValidWithRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;Ao compilar a expressão regular uma vez e reutilizá-la, você reduz significativamente o impacto de performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Embora regex seja uma ferramenta poderosa e útil, seu uso em validações simples pode ser ineficiente, especialmente quando a performance é uma prioridade. Em Go, alternativas como a utilização da biblioteca unicode podem oferecer ganhos significativos de performance. Se for necessário usar regex, lembre-se de compilar a expressão regular fora do método para otimizar o desempenho.&lt;/p&gt;

&lt;p&gt;Agora, repense como você está validando suas strings no seu projeto e escolha a abordagem mais eficiente para o seu caso!&lt;/p&gt;

</description>
      <category>go</category>
      <category>regex</category>
      <category>unicode</category>
      <category>benchmark</category>
    </item>
    <item>
      <title>Criando meu pacote de erro usando Go</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Tue, 02 Jan 2024 19:35:20 +0000</pubDate>
      <link>https://dev.to/renanbastos93/criando-meu-pacote-de-erro-usando-go-76</link>
      <guid>https://dev.to/renanbastos93/criando-meu-pacote-de-erro-usando-go-76</guid>
      <description>&lt;p&gt;Neste artigo, vamos dar um rolê pela criação de erros usando Golang, ou seja, com sua biblioteca padrão. Depois desse aquecimento, vamos mergulhar no desenvolvimento do nosso próprio pacote.&lt;/p&gt;

&lt;p&gt;Se você ainda não está familiarizado ou não manja muito de interfaces em Golang, eu super recomendo dar uma lida nesse &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-interfaces-in-go-pt" rel="noopener noreferrer"&gt;artigo&lt;/a&gt; antes, porque a coisa vai ficar intensa. Vamos explorar os pacotes padrão e desvendar como podemos usá-los para construir algo incrível. Então, prepara o café e vem comigo nessa jornada pelos segredos dos pacotes em Golang. Bora nessa?&lt;/p&gt;




&lt;p&gt;Para começar, vamos explorar duas maneiras simples de criar erros em Golang, utilizando as bibliotecas padrão 'errors' e 'fmt'. Essas são ferramentas poderosas que vão nos permitir adicionar um toque personalizado aos nossos erros e deixar nossa aplicação mais robusta. Vamos lá!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Usando o pacote &lt;a href="https://pkg.go.dev/errors" rel="noopener noreferrer"&gt;errors&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed operation"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Aqui vai retornar um novo erro com a mensagem `failed operation`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Usando o pacote &lt;a href="https://pkg.go.dev/fmt#Errorf" rel="noopener noreferrer"&gt;fmt&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed again"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Aqui vai retornar um novo erro com a mensagem `failed again`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma característica fascinante do pacote fmt é a liberdade que ele oferece para personalizar os erros. Além disso, podemos dar um toque especial ao envolvê-los utilizando a referência %w. Vamos dar uma olhada prática nisso com um exemplo:&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="n"&gt;errOp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed operation"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Cria um novo erro&lt;/span&gt;
&lt;span class="n"&gt;errAgain&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%w: again"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errOp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Cria um novo erro que obtém como principal o `errOp`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa abordagem não apenas permite personalizar os erros, mas também oferece uma maneira inteligente de repassar informações sem a necessidade de fazer log em cada camada do código. Ao herdar o erro anterior e manter a mesma raiz, conseguimos construir um rastreamento completo do erro, proporcionando uma visão clara da jornada do problema. Uma técnica que não só simplifica, mas também enriquece o processo de identificação e resolução de falhas em nosso código.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Agora, acredito que estamos prontos para dar o próximo passo e criar nosso próprio pacote, respeitando a interface error e aproveitando as funcionalidades do pacote padrão error. Bora lá!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Para iniciar essa jornada incrível, vamos criar uma estrutura personalizada. Vamos seguir a ideia de ter um erro com um código e uma mensagem, algo semelhante aos erros que encontramos no dia a dia das APIs REST. Essa abordagem não apenas facilita a identificação e tratamento de erros, mas também adiciona uma camada de clareza ao nosso código. Vamos colocar a mão na massa e ver o que conseguimos construir juntos!&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;myError&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;code&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que temos nossa &lt;code&gt;struct&lt;/code&gt; para representar erros personalizados na aplicação, o próximo passo é criar um método que não apenas instancie o erro, mas também retorne uma interface error. Dessa forma, nossa aplicação pode integrar suavemente esses erros personalizados ao fluxo padrão de manipulação de erros em Golang. Vamos criar esse método e garantir que nossos erros sejam facilmente utilizáveis!&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;func&lt;/span&gt; &lt;span class="n"&gt;NewError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&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;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;myError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&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;Vale destacar um ponto crucial que frequentemente é negligenciado e resulta em retrabalho desnecessário: muitas pessoas cometem o equívoco de retornar diretamente o ponteiro da estrutura na assinatura do método, em vez da interface error. Essa prática pode gerar complicações adicionais durante validações e manipulação de erros.&lt;/p&gt;

&lt;p&gt;Para concluir nosso contrato, vamos adicionar um método &lt;code&gt;Error() string&lt;/code&gt;. Esse método é essencial, pois atende ao contrato definido pela interface error, garantindo que nossos erros personalizados possam ser facilmente integrados e utilizados em qualquer contexto que espera uma implementação da interface error. Vamos fortalecer a base do nosso pacote, deixando-o ainda mais robusto e eficiente.&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;myError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Error&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msg&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;Caramba, pessoal, não é que nosso pacote está pronto? E que tal irmos além e testarmos isso na prática? Vamos fazer um teste repassando nosso erro para frente, utilizando a técnica de wrap com outro erro, e em seguida, validar se o tipo do erro foi herdado corretamente. Ah, vai ser legal! Vamos lá, é hora de entrar nesse teste e garantir que nosso pacote está afiado. Go go go!&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="c"&gt;// Criando um erro bad request&lt;/span&gt;
&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bad request"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Envelopando o erro not found dentro do bad request&lt;/span&gt;
&lt;span class="n"&gt;errAgain&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%w: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"not found"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c"&gt;// output:&lt;/span&gt;
&lt;span class="c"&gt;// 400: bad request: 404: not found&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errAgain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Aqui estamos validando se o errAgain é herdado do bad request&lt;/span&gt;
&lt;span class="c"&gt;// output&lt;/span&gt;
&lt;span class="c"&gt;// true&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errAgain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c"&gt;// Aqui a gente remove o errAgain e pega somente o original&lt;/span&gt;
&lt;span class="c"&gt;// output&lt;/span&gt;
&lt;span class="c"&gt;// 400: bad request&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unwrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errAgain&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em conclusão, a valorização e aplicação adequada das interfaces nativas do Go, com destaque para a interface error, revelam-se cruciais. Ao respeitar esses padrões, não apenas fortalecemos a consistência do código, mas também habilitamos rastreamentos mais eficientes quando necessários. Essa abordagem não apenas eleva a qualidade do código, mas também promove a reutilização, consolidando a robustez e flexibilidade no desenvolvimento em Go. Vamos adotar esses princípios para aprimorar continuamente nossa prática de programação em Go.&lt;/p&gt;

&lt;p&gt;Para ver o código completo, &lt;a href="https://gist.github.com/renanbastos93/f63538b4e75d0bd0fc2d56537206f186" rel="noopener noreferrer"&gt;acesse aqui&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>go</category>
      <category>interface</category>
      <category>errors</category>
      <category>pkg</category>
    </item>
    <item>
      <title>Como Fazer Restore do MongoDB usando mongorestore com Arquivos wiredTriger</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Sun, 03 Dec 2023 18:13:57 +0000</pubDate>
      <link>https://dev.to/renanbastos93/como-fazer-restore-do-mongodb-usando-mongorestore-com-arquivos-wiredtriger-47af</link>
      <guid>https://dev.to/renanbastos93/como-fazer-restore-do-mongodb-usando-mongorestore-com-arquivos-wiredtriger-47af</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;E aí, pessoal! Sejam todos bem-vindos a este guia prático de como realizar a restauração de um backup no MongoDB usando a ferramenta mongorestore. Mas peraí, aqui tem um toque especial – estamos falando de uma restauração com a ausência dos arquivos padrão .bson e a presença dos misteriosos arquivos .wt, também conhecidos como WiredTiger. Vamos desbravar esse terreno e entender como essa peculiaridade pode proporcionar uma compreensão ainda maior do processo. Bora lá! 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  Contexto e ferramentas
&lt;/h2&gt;

&lt;p&gt;Para começar esta jornada, gostaria de compartilhar que recebi esse dump do time de SRE para realizar uma restauração em outro ambiente, simulando assim um cenário real. Curiosamente, a base de dados na época tinha 8GB. Então, vamos lá! Para iniciar, precisamos instalar as ferramentas do MongoDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;mongodb-database-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, dispomos de algumas ferramentas úteis para interagir com o MongoDB, como o mongodump e o mongorestore. Neste tutorial, concentraremos nossa atenção no &lt;code&gt;workaround&lt;/code&gt; utilizando o mongorestore para lidar com o cenário específico em que possuímos apenas os arquivos WiredTiger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualizando os erros
&lt;/h2&gt;

&lt;p&gt;Bom, quais foram os erros que ocorreram ao tentar utilizar o mongorestore? Na verdade, tive apenas dois erros e tentei diversos workarounds que não obtiveram sucesso. Vamos analisar o comando e o respectivo output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mongorestore &lt;span class="nt"&gt;--username&lt;/span&gt; adminuser &lt;span class="nt"&gt;--password&lt;/span&gt; password123 mongodb://127.0.0.1:27017 &lt;span class="nt"&gt;--gzip&lt;/span&gt; dump.tar.gz
&lt;span class="c"&gt;# 2023-11-30T11:26:18.319-0300  Failed: file dump.tar.gz does not have .bson extension&lt;/span&gt;

&lt;span class="c"&gt;# Outra tentativa&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;mongorestore &lt;span class="nt"&gt;--username&lt;/span&gt; adminuser &lt;span class="nt"&gt;--password&lt;/span&gt; password123 mongodb://127.0.0.1:27017 &lt;span class="nt"&gt;--dir&lt;/span&gt; restore-656867ceae3af1227ffa3f59/
&lt;span class="c"&gt;# 2023-11-30T11:28:10.196-0300  preparing collections to restore from&lt;/span&gt;
&lt;span class="c"&gt;# 2023-11-30T11:28:10.199-0300  don't know what to do &lt;/span&gt;
&lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;span class="c"&gt;# 2023-11-30T11:28:10.201-0300  0 document(s) restored successfully. 0 document(s) failed to restore.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Percebemos que, neste caso, não foi possível realizar a restauração conforme o esperado. No entanto, este era o único dump disponível. Diante desse desafio, iniciei uma pesquisa extensiva, explorando várias alternativas em documentações e workarounds. Agora, vamos examinar uma solução que se mostrou eficaz para o meu cenário. Reconheço que pode haver métodos mais simples e precisos, então se alguém tiver alguma sugestão, não hesite em compartilhar nos comentários. Vamos lá!&lt;/p&gt;

&lt;h2&gt;
  
  
  Pensando na solução e executando
&lt;/h2&gt;

&lt;p&gt;É interessante mencionar que você pode tanto configurar o MongoDB localmente quanto utilizar uma imagem Docker. Pessoalmente, optei por utilizar uma imagem Docker, mas para facilitar o entendimento, vou demonstrar como configurar um MongoDB local sem o uso do Docker.&lt;/p&gt;

&lt;p&gt;Se o MongoDB ainda não estiver instalado em sua máquina, basta realizar a instalação da maneira que for mais conveniente para você. Em seguida, subiremos o servidor via linha de comando utilizando o comando &lt;code&gt;mongod&lt;/code&gt; e especificando o caminho para o nosso dump.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mongod &lt;span class="nt"&gt;--dbpath&lt;/span&gt; ~/dump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, podemos observar que ele conseguiu identificar os arquivos do WiredTiger. Ou seja, o que precisamos fazer agora é gerar um dump desta base que nos forneça os arquivos BSON. Esses arquivos são essenciais para serem utilizados na restauração do nosso ambiente.&lt;br&gt;
Vamos executar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mongodump &lt;span class="nt"&gt;--host&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;-u&lt;/span&gt; myuser &lt;span class="nt"&gt;-p&lt;/span&gt; mypass &lt;span class="nt"&gt;-d&lt;/span&gt; mydatabase &lt;span class="nt"&gt;--port&lt;/span&gt; 27017 &lt;span class="nt"&gt;--out&lt;/span&gt; newDump &lt;span class="nt"&gt;--authenticationDatabase&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beleza, galera! Agora temos um dump novinho em folha com os arquivos BSON. Uhull! E agora, partiu fazer o restore? 🚀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mongorestore &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="nt"&gt;--username&lt;/span&gt; adminuser &lt;span class="nt"&gt;--password&lt;/span&gt; password123 mongodb://127.0.0.1:27017 newDump

&lt;span class="c"&gt;# 2023-12-01T11:19:17.148-0300  [###.....................]  mydatabase.Collection  1.26GB/8.03GB  (15.7%)&lt;/span&gt;
&lt;span class="c"&gt;# 2023-12-01T11:19:17.148-0300  [#######################.]     mydatabase.Collection  2.95GB/2.96GB  (99.5%)&lt;/span&gt;
&lt;span class="c"&gt;# 2023-12-01T11:19:17.148-0300  &lt;/span&gt;
&lt;span class="c"&gt;# 2023-12-01T11:19:18.878-0300  [########################]  mydatabase.Collection  2.96GB/2.96GB  (100.0%)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Encerrando nossa odisséia pelo universo MongoDB, superamos perrengues, desbravamos soluções e agora brindamos a um novo dump com arquivos BSON. Uhull! Estamos prontos para restaurar e esse processo, embora não seja a única trilha, certamente clareia o caminho para quem encara dilemas similares. Se tiver truques ou dicas na manga, bota aí nos comentários. Juntos, fortalecemos a rede de conhecimento, inspirando novas explorações. Na jornada do aprendizado, cada desafio é um convite para avançar. Até a próxima aventura, exploradores digitais! 🌟🚀&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>wiredtriger</category>
      <category>restore</category>
      <category>bson</category>
    </item>
    <item>
      <title>Qual a diferença de usar um receiver com ou sem ponteiro em Go?</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Mon, 25 Sep 2023 12:52:41 +0000</pubDate>
      <link>https://dev.to/renanbastos93/qual-a-diferenca-de-usar-um-receiver-com-ou-sem-ponteiro-em-go-2do8</link>
      <guid>https://dev.to/renanbastos93/qual-a-diferenca-de-usar-um-receiver-com-ou-sem-ponteiro-em-go-2do8</guid>
      <description>&lt;p&gt;Recentemente, tive a incrível oportunidade de participar de um dos maiores eventos de &lt;a href="https://go.dev/" rel="noopener noreferrer"&gt;Golang&lt;/a&gt; da América Latina, a &lt;a href="https://gopherconbr.org/" rel="noopener noreferrer"&gt;Gophercon BR&lt;/a&gt;. Gostaria de expressar minha gratidão aos organizadores e a todos que estiveram presentes no evento, pois proporcionaram um ambiente incrível para networking e aprendizado.&lt;/p&gt;

&lt;p&gt;Durante o evento, tive um encontro interessante com um rapaz chamado &lt;a href="https://www.linkedin.com/in/joao-salvador-rizzo/" rel="noopener noreferrer"&gt;João Salvador&lt;/a&gt;. Ele apresentou um desafio intrigante, exibindo um código que imediatamente despertou minha curiosidade e fez meus neurônios entrarem em ação para decifrá-lo. A experiência de resolver esse desafio foi estimulante e educativa, e, após concluí-lo, senti a necessidade de compartilhar esse conhecimento com a comunidade.&lt;/p&gt;

&lt;p&gt;Neste post, estou entusiasmado em apresentar o desafio proposto por João Salvador e explicar os detalhes por trás dele. Acredito que a compreensão deste desafio trará uma nova perspectiva sobre o uso de receivers com ou sem ponteiro em Go, proporcionando insights valiosos que podem expandir nossos horizontes e ajudar muitas pessoas a aprofundar seu entendimento da linguagem.&lt;/p&gt;




&lt;h3&gt;
  
  
  Desafio que me foi Apresentado no Evento
&lt;/h3&gt;

&lt;p&gt;O que você espera que o console imprima? Pense bem antes de continuar lendo, isso vai enriquecer ainda mais sua compreensão no tópico em questão&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%2Fyssd1dij64xzc0sg4rgk.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%2Fyssd1dij64xzc0sg4rgk.png" alt=" " width="739" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comente a sua resposta!&lt;/p&gt;




&lt;h3&gt;
  
  
  Agora iremos juntos entender e desvendar a solução
&lt;/h3&gt;

&lt;p&gt;Vamos começar nossa jornada entendendo que temos uma estrutura chamada "Person". Cada instância dessa estrutura possui um atributo chamado "Name", que armazena o nome de uma pessoa. Além disso, esta estrutura é enriquecida com um método chamado "SayHi", que é acionado por meio de um conceito conhecido como "receiver". A função principal deste método é simples, ele imprime na tela uma saudação, "Hi", seguida pelo nome da pessoa.&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="c"&gt;// Declarada a estrutura Person&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&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;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// SayHi vai printar uma saudação Hi seguida com o nome da pessoa&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayHi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi %s!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&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;h3&gt;
  
  
  Tá! Mas o que é receiver?
&lt;/h3&gt;

&lt;p&gt;É um parâmetro especial em um método de um tipo definido pelo usuário (struct) que permite que esse método seja chamado em instâncias desse tipo. O receiver é semelhante ao conceito de um objeto em orientação a objetos, mas é específico para métodos em Go.&lt;/p&gt;

&lt;p&gt;Observamos que o método &lt;code&gt;SayHi&lt;/code&gt; utiliza um receiver de valor, o que significa que, nesse contexto, o método atua em uma cópia do valor original do tipo. Isso implica que qualquer alteração efetuada dentro do método não terá efeito sobre a instância original desse tipo.&lt;/p&gt;

&lt;p&gt;Agora que entendemos isso vamos ver como funciona um &lt;code&gt;receiver&lt;/code&gt; de ponteiro. Ou seja, o método opera diretamente na instância original do tipo, pois recebe um ponteiro para ela. Isso permite que o método modifique o valor da instância original.&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;UpdateName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newName&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newName&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que entendemos ambos os casos comentado a cima, vamos criar nossa &lt;code&gt;func main()&lt;/code&gt; para visualizar e entender os outputs gerados.&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;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Renan"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayHi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;              &lt;span class="c"&gt;// Output: Hi Renan!&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayHi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}()&lt;/span&gt; &lt;span class="c"&gt;// Output: Hi Renan Bastos!&lt;/span&gt;

    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Renan Bastos"&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;Parece bruxaria mas não é, os dois &lt;code&gt;defer&lt;/code&gt; imprimiram valores diferentes porque o defer empilha uma cópia da estrutura no primeiro e uma função anônima no segundo. Portanto, quando o defer é executado, ele já capturou a alteração no campo Name. O defer funciona como uma pilha, executando o último defer chamado primeiro e desempilhando conforme cada um é executado.&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="c"&gt;// Output final&lt;/span&gt;
&lt;span class="c"&gt;// Output: Hi Renan Bastos!&lt;/span&gt;
&lt;span class="c"&gt;// Output: Hi Renan!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Neste artigo, exploramos o conceito de receiver em Go e a utilidade do defer. Uma questão frequente é quando devemos optar por usar um receiver de ponteiro. A escolha depende das necessidades específicas de seu programa e do comportamento desejado, e não existe uma resposta única. Portanto, a melhor abordagem é avaliar cuidadosamente o contexto de seu código e escolher entre receiver de valor ou de ponteiro com base nas exigências do projeto.&lt;/p&gt;

</description>
      <category>go</category>
      <category>receiver</category>
      <category>ponteiro</category>
      <category>defer</category>
    </item>
    <item>
      <title>Criando um JSON Unmarshal personalizado em Go</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Wed, 13 Sep 2023 11:58:54 +0000</pubDate>
      <link>https://dev.to/renanbastos93/como-faco-para-substituir-o-unmarshaljson-corretamente-4o2m</link>
      <guid>https://dev.to/renanbastos93/como-faco-para-substituir-o-unmarshaljson-corretamente-4o2m</guid>
      <description>&lt;p&gt;Neste breve tutorial, vamos explorar como criar um método UnmarshalJSON personalizado em Go, adaptando-o para uma situação em que temos um campo específico na estrutura que pode ser representado como número, booleano ou string. Isto nos permitirá lidar com dados JSON de forma flexível e personalizada.&lt;/p&gt;




&lt;p&gt;Vamos prosseguir com um exemplo prático usando a estrutura "King" com os campos "Active" e "Name". Vamos começar a criar o método &lt;code&gt;UnmarshalJSON&lt;/code&gt; personalizado para lidar com o campo "Active" que pode ser representado como número, booleano ou string.&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;King&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;Name&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"name"`&lt;/span&gt;
    &lt;span class="n"&gt;Active&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;   &lt;span class="s"&gt;`json:"active,string"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;//Após criar a estrutura vamos implementar a função para o UnmarshalJSON personalizado.&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;UnmarshalJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Criamos um mapa dinâmico para armazenar os campos JSON.&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fields&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="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c"&gt;// Realizamos a decodificação JSON padrão no mapa "fields".&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;fields&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Copiamos o valor do campo "name" do mapa para a estrutura "King".&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&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="c"&gt;// Convertendo o valor do campo "active" para booleano.&lt;/span&gt;
    &lt;span class="c"&gt;// Usamos `fmt.Sprintf` para garantir que o valor seja uma string antes da conversão.&lt;/span&gt;
    &lt;span class="n"&gt;activeStr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="c"&gt;// Aqui estamos convertendo para boleano e ignoramos o erro pois se vier algo diferente do esperado sempre será falso&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;activeStr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que entendemos como criar um Unmarshal JSON personalizado, vamos aplicar isso na função principal, chamada 'main', do pacote principal. A seguir, apresentamos o código com os resultados esperados.&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;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="n"&gt;King&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": 1, "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%+v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// Output: {Name:renan Active:true}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para concluir, demonstraremos um teste unitário usando nosso método personalizado, abrangendo todos os casos para uma compreensão abrangente.&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;func&lt;/span&gt; &lt;span class="n"&gt;TestKing_UnmarshalJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&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;name&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;king&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;
        &lt;span class="n"&gt;wantErr&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Employing the number 1 to denote a true value."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": 1, "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Employing the number 0 to denote a false value."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": 0, "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Utilizing the string '1' to represent the boolean value 'true'."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": "1", "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Utilizing the string '0' to represent the boolean value 'false'."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": "0", "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Utilizing the string 'true' to represent the boolean value 'true'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": "true", "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Utilizing the bool true to represent the boolean value 'true'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": true, "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Utilizing the bool false to represent the boolean value 'false'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": false, "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"Utilizing the string 'false' to represent the boolean value 'false'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;King&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"renan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"active": "false", "name":"renan"}`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tt&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;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="n"&gt;King&lt;/span&gt;
            &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wantErr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"King.UnmarshalJSON() error = %v, wantErr %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="p"&gt;)&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;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Active&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Active&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unmarshal failed: k[%+v]; tt.kink[%+v];"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;king&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&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;Agradeço por acompanhar este tutorial. Se você tiver alguma dúvida, comentário ou sugestão, por favor, não hesite em entrar em contato comigo. Estou à disposição para ajudar e melhorar.&lt;/p&gt;

</description>
      <category>go</category>
      <category>unmarshal</category>
      <category>struct</category>
      <category>json</category>
    </item>
    <item>
      <title>Boneless: a CLI to create your apps with Go</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Wed, 28 Jun 2023 16:48:43 +0000</pubDate>
      <link>https://dev.to/renanbastos93/boneless-a-cli-to-create-your-apps-with-go-31kh</link>
      <guid>https://dev.to/renanbastos93/boneless-a-cli-to-create-your-apps-with-go-31kh</guid>
      <description>&lt;p&gt;Boneless is a powerful tool that offers a wide range of features to facilitate application development. In this blog post, we will explore some essential tools that can be used in conjunction with &lt;a href="https://github.com/renanbastos93/boneless" rel="noopener noreferrer"&gt;Boneless&lt;/a&gt;: &lt;a href="https://serviceweaver.dev/" rel="noopener noreferrer"&gt;Service Weaver&lt;/a&gt;, &lt;a href="https://github.com/golang-migrate/migrate/tree/master/cmd/migrate#installation" rel="noopener noreferrer"&gt;Go Migrate&lt;/a&gt;, &lt;a href="https://docs.sqlc.dev/en/stable/overview/install.html" rel="noopener noreferrer"&gt;SQLC&lt;/a&gt;, and &lt;a href="https://gofiber.io/" rel="noopener noreferrer"&gt;Fiber&lt;/a&gt;. Let's discover how these tools can boost productivity and efficiency in application development.&lt;/p&gt;




&lt;p&gt;After setting the context and providing a comprehensive introduction, we will demonstrate how to use our CLI. First, we need to install the necessary CLI tools.&lt;/p&gt;




&lt;p&gt;By the way, first, we need to install the binary of Service Weaver, Go Migrate, SQLC, and Boneless. Even so, I suggest you read the documentation of all of them on your official websites.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-tags&lt;/span&gt; &lt;span class="s1"&gt;'mysql sqlite3'&lt;/span&gt; github.com/golang-migrate/migrate/v4/cmd/migrate@latest
&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/sqlc-dev/sqlc/cmd/sqlc@latest
&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/ServiceWeaver/weaver/cmd/weaver@latest
&lt;span class="nv"&gt;$ &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/renanbastos93/boneless/cmd/boneless@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, let's go on an adventure&lt;/p&gt;




&lt;h3&gt;
  
  
  Create scratch project
&lt;/h3&gt;

&lt;p&gt;Always remember to check the available methods by executing &lt;code&gt;boneless help&lt;/code&gt;. After that, we can proceed to create a new folder and a &lt;code&gt;go.mod&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; myapp
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;myapp
&lt;span class="nv"&gt;$ &lt;/span&gt;go mod tidy myapp

&lt;span class="c"&gt;# "Now we can start utilizing commands from Boneless&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;boneless create-scratch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the project, we can go ahead and execute it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ SERVICEWEAVER_CONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./weaver.toml"&lt;/span&gt; boneless run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding a New app
&lt;/h3&gt;

&lt;p&gt;If you want to add a new component to your application built with Boneless, the process is straightforward. Here are the steps you can follow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;boneless create-app user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you need to make changes according to your requirements.&lt;/p&gt;

&lt;p&gt;In addition, there are other Boneless commands available that you can use when they are truly necessary. See below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;boneless &lt;span class="nb"&gt;help
&lt;/span&gt;Usage: boneless &lt;span class="o"&gt;[&lt;/span&gt;target]

Targets:
  &lt;span class="nb"&gt;help                                     &lt;/span&gt;Show commands &lt;span class="k"&gt;for &lt;/span&gt;use
  version                                  Show version
  new  &amp;lt;sql|sqlite3&amp;gt;                       Create a project from scratch using Weaver, SQLC, and go-migrate
  create-scratch &amp;lt;sql|sqlite3&amp;gt;             Create a project from scratch using Weaver, SQLC, and go-migrate
  build                                    Build the Weaver component with SQLC
  make-migrate &amp;lt;app-name&amp;gt; &amp;lt;name&amp;gt;           Create a new migration &lt;span class="k"&gt;for &lt;/span&gt;an app
  migrate &amp;lt;app-name&amp;gt; &amp;lt;up|down&amp;gt;             Run migrations &lt;span class="k"&gt;for &lt;/span&gt;an app
  create-app &amp;lt;app-name&amp;gt;                    Create a new app based on a template
  build-app &amp;lt;app-name&amp;gt;                     Build an app using Weaver and SQLC
  run                                      Run the project using Weaver

Parameters:
  &amp;lt;app-name&amp;gt;                               Name of the app to create or run migrations on
  &amp;lt;name&amp;gt;                                   Name of the migration to create
  &amp;lt;up|down&amp;gt;                                Specify &lt;span class="s2"&gt;"up"&lt;/span&gt; to apply migrations or &lt;span class="s2"&gt;"down"&lt;/span&gt; to rollback migrations
  &amp;lt;sql|sqlite&amp;gt;                             Specify &lt;span class="s2"&gt;"sql"&lt;/span&gt; to use some SQL &lt;span class="s2"&gt;"sqlite3"&lt;/span&gt; to use sqlite3 and it is the default

Examples:
  boneless &lt;span class="nb"&gt;help
  &lt;/span&gt;boneless version
  boneless create-scratch
  boneless build
  boneless make-migrate my-app migration-name
  boneless migrate my-app up
  boneless create-app my-app
  boneless build-app my-app
  boneless run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In summary, we have explored the powerful tools available for application development using Boneless. We discussed the Command Line Interface (CLI) that facilitates the creation of web applications, along with Service Weaver, Go Migrate, SQLC, and Fiber. These tools provide essential features to boost productivity and efficiency in developing distributed applications, managing database migrations, generating secure code, and building fast web applications.&lt;/p&gt;

&lt;p&gt;By utilizing these tools together, developers have a wide range of resources at their disposal to create robust, scalable, and secure applications. Through the Boneless CLI, you can initiate projects, manage database migrations, and leverage the benefits of Service Weaver and Fiber to build efficient and responsive APIs.&lt;/p&gt;

&lt;p&gt;We hope this article has provided a comprehensive overview of these tools and sparked your interest in further exploring the potential of Boneless and its components. With the right combination of tools and knowledge, you will be well-positioned to develop high-quality web applications.&lt;/p&gt;

</description>
      <category>go</category>
      <category>serviceweaver</category>
      <category>fiber</category>
      <category>gomigrate</category>
    </item>
    <item>
      <title>How to verify if the context has a deadline</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Tue, 31 Jan 2023 01:17:01 +0000</pubDate>
      <link>https://dev.to/renanbastos93/how-to-verify-if-my-context-has-a-deadline-4268</link>
      <guid>https://dev.to/renanbastos93/how-to-verify-if-my-context-has-a-deadline-4268</guid>
      <description>&lt;p&gt;It's very simple, &lt;code&gt;context.Context&lt;/code&gt; has a little method called Deadline that returns &lt;code&gt;(deadline time.Time, ok bool)&lt;/code&gt;. When the ok variable is true, the deadline is set. Why use a deadline? We need to use it to set a time to cancel the operation, e.g. we need to wait for max 3 seconds to execute a query on the database, in case overtakes the time, context will call cancel in the operation.&lt;/p&gt;

&lt;p&gt;See the example below:&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;func&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CancelFunc&lt;/span&gt;&lt;span class="p"&gt;)&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;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hasDeadline&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deadline&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;hasDeadline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;Now, let's see an example using this method in an operation that prints a message many times.&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;func&lt;/span&gt; &lt;span class="n"&gt;usingSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something message!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&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;Well, I believe that it’s interesting to share the unit test as well.&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;func&lt;/span&gt; &lt;span class="n"&gt;TestSomethingWithDeadline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"using timeout of 1s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hasDeadline&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deadline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EqualValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hasDeadline&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestSomethingWithoutDeadline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"using default timeout of something method"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hasDeadline&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deadline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EqualValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hasDeadline&lt;/span&gt;&lt;span class="p"&gt;)&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;That's what I wanted to show here. I hope this helps!&lt;/p&gt;

</description>
      <category>go</category>
      <category>context</category>
      <category>deadline</category>
      <category>timeout</category>
    </item>
  </channel>
</rss>
