<?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.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>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>
    <item>
      <title>Do we must implements unit test just to have coverage?</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Fri, 28 Oct 2022 21:18:33 +0000</pubDate>
      <link>https://dev.to/renanbastos93/do-we-must-implements-unit-test-just-to-have-coverage-1gm2</link>
      <guid>https://dev.to/renanbastos93/do-we-must-implements-unit-test-just-to-have-coverage-1gm2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Sharing a feeling&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since I have started my career I saw many tests in many pull requests, code, etc..., most of the time all people only wish &lt;strong&gt;&lt;strong&gt;have coverage&lt;/strong&gt;&lt;/strong&gt;. However, this is not good practice because all the tests that we need to implement in our codes should behave according to business rules to simulate whole cases based on your essence.&lt;/p&gt;

&lt;p&gt;thanks a lot to read it&lt;/p&gt;

&lt;p&gt;best regards&lt;br&gt;
see ya&lt;/p&gt;

</description>
      <category>tests</category>
      <category>coverage</category>
      <category>unittest</category>
      <category>myopinion</category>
    </item>
    <item>
      <title>Using redirect middleware with GoFiber</title>
      <dc:creator>renanbastos93</dc:creator>
      <pubDate>Thu, 16 Dec 2021 10:21:21 +0000</pubDate>
      <link>https://dev.to/renanbastos93/using-redirect-middleware-with-gofiber-1n37</link>
      <guid>https://dev.to/renanbastos93/using-redirect-middleware-with-gofiber-1n37</guid>
      <description>&lt;p&gt;Well, let's start to learn more about using a redirect middleware with Fiber. Today, I am a commuter in this project and talking with members about new features, fixes, etc. Let's see the following steps below:&lt;/p&gt;




&lt;p&gt;1 - Introduction Fiber&lt;br&gt;
2 - About redirect middleware&lt;br&gt;
3 - Show me the code&lt;br&gt;
4 - Conclusion&lt;/p&gt;



&lt;p&gt;1) So, is a framework to implement an API Rest using &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;Golang&lt;/a&gt;. It was based on &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;ExpressJS&lt;/a&gt; on its type of using, but if we use FastHttp, we can gain much more performance of memory. The smallest problem is that we don't compatible frameworks yet with &lt;a href="https://tools.ietf.org/html/rfc7540" rel="noopener noreferrer"&gt;http/2.0&lt;/a&gt; but the [FastHttp](&lt;a href="https://godoc.org/github.com/valyala/fasthttp" rel="noopener noreferrer"&gt;https://godoc.org/github.com/valyala/fasthttp&lt;/a&gt; it's being already implemented and coming soon, so we can use it.&lt;/p&gt;

&lt;p&gt;2) Redirect middleware was implemented to create rules to routes definition according to the business rule of the application. You can see documentation about middleware at directly &lt;a href="//fiber.wiki"&gt;fiber.wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) Let's work!&lt;br&gt;
To start our code we need to install two modules the &lt;code&gt;gofiber/fiber&lt;/code&gt; and &lt;code&gt;gofiber/redirect&lt;/code&gt;. One detail very important is: don't forget to init your module &lt;code&gt;go mod init &amp;lt;your-module&amp;gt;&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;&lt;span class="nv"&gt;$ &lt;/span&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/gofiber/fiber
&lt;span class="nv"&gt;$ &lt;/span&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/gofiber/redirect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can implement the first code for this we go to create a file main.go. Later, we must start your package name main and create your function main. &lt;br&gt;
In this snippet of code, we create an API without routes and instance the redirect middleware without rules.&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;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;"github.com/gofiber/fiber"&lt;/span&gt;
  &lt;span class="s"&gt;"github.com/gofiber/redirect"&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;app&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fiber&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="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redirect&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="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3000&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;Let's define our business rules:&lt;br&gt;
we can presume that the API has to have routes to old and new and, then we wish that the old routes could do a redirect for new routes. Show me the code...&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="c"&gt;// ...  &lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redirect&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="n"&gt;redirect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Rules&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;"/old"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"/new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"/old/*"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/new/$1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"/wow"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://fiber.wiki"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to the last snippet , we can understand that you also can use redirect to external routes. Now, let's go to create 2 new routes:&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;// ...&lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/new"&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;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fiber&lt;/span&gt;&lt;span class="o"&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;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/new/*"&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;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fiber&lt;/span&gt;&lt;span class="o"&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;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Wildcard: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Params&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="c"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As soon as you have done, we can go start, run and test our API&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 run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later open a new terminal we can running the tests using cURL.&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;curl &lt;span class="nt"&gt;-svk&lt;/span&gt; http://localhost:3000/old
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-svk&lt;/span&gt; http://localhost:3000/old/hello
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-svk&lt;/span&gt; http://localhost:3000/wow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) But don't forget, we realized with this tutorial that this framework is very easy to use and we can create powerful rules to redirect from your API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/renanbastos93/9d5e50b8cffd1c933d96bd80567848ec" rel="noopener noreferrer"&gt;Gist this code&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>fiber</category>
      <category>redirect</category>
      <category>middleware</category>
    </item>
  </channel>
</rss>
