<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Diário - Cesar Gimenes</title><link>https://crg.eti.br/pt-br/jnl/</link><description>Entradas do diário de Cesar Gimenes</description><generator>Hugo -- gohugo.io</generator><language>pt-br</language><managingEditor>crg@crg.eti.br (Cesar Gimenes)</managingEditor><webMaster>crg@crg.eti.br (Cesar Gimenes)</webMaster><lastBuildDate>Mon, 02 Mar 2026 07:50:59 -0300</lastBuildDate><atom:link href="https://crg.eti.br/pt-br/jnl/index.xml" rel="self" type="application/rss+xml"/><item><title>Recordando o passado e esclarecendo a regra contra pirataria</title><link>https://crg.eti.br/pt-br/jnl/2026-03-02t07-51-50-recordando-o-passado/</link><pubDate>Mon, 02 Mar 2026 07:50:59 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2026-03-02t07-51-50-recordando-o-passado/</guid><description>&lt;h1 id="recordando-o-passado-e-esclarecendo-a-regra-contra-pirataria">Recordando o passado e esclarecendo a regra contra pirataria&lt;/h1>
&lt;p>O Grupo de Estudos de Go surgiu há mais de dez anos, a partir de um workshop realizado no ABC Makerspace, um hackerspace do ABC Paulista que, à época, funcionava dentro da minha empresa.&lt;/p>
&lt;p>No início, o grupo sequer tinha nome. Era apenas um conjunto de amigos que participavam dos encontros do hackerspace. O espaço ainda existe, hoje mantido no campus da UFABC. Confesso que sinto certo orgulho ao ver fotos recentes e reconhecer as mesas que eu mesmo construí. A solução é simples e econômica: portas, cavaletes e tinta.&lt;/p>
&lt;p>Quando encerrei as atividades da empresa, o grupo migrou para o formato online e passou por diversas plataformas: Facebook, Google Meet, Slack, entre outras. O repositório sempre esteve no GitHub. Com o tempo, a estrutura se estabilizou: GitHub para código, YouTube para vídeos, Telegram para comunicação e Discord para encontros.&lt;/p>
&lt;p>O principal problema desse modelo é que parte significativa do conhecimento produzido nas discussões fica restrita a plataformas que exigem login. Isso dificulta o acesso de quem está começando e procura material aberto na internet.&lt;/p>
&lt;hr>
&lt;h2 id="sobre-a-regra-contra-pirataria">Sobre a regra contra pirataria&lt;/h2>
&lt;p>Não se trata de uma posição moralista contra pirataria. Pessoalmente, acredito que o conhecimento deveria ser livre e que patentes de software não deveriam existir.&lt;/p>
&lt;p>No entanto, a divulgação de material sem autorização prejudica quem se dedica a produzir conteúdo aberto e legítimo. Esse é o único motivo pelo qual não permitimos a publicação de links ou materiais sem a devida permissão dos autores.&lt;/p>
&lt;hr>
&lt;h2 id="tornando-o-material-mais-público">Tornando o material mais público&lt;/h2>
&lt;p>Sempre houve tentativas de tornar o conhecimento gerado pelo grupo mais acessível. Na prática, isso é mais complexo do que parece. As pessoas tendem a permanecer na plataforma em que já estão, mesmo com suas limitações.&lt;/p>
&lt;p>A iniciativa mais recente é o desenvolvimento do &lt;code>empreendedor.dev&lt;/code>, que já resultou em diversas bibliotecas e códigos relevantes. O avanço, no entanto, é lento, em função de outros projetos paralelos que também demandam atenção.&lt;/p>
&lt;hr>
&lt;h2 id="o-canal-no-telegram">O canal no Telegram&lt;/h2>
&lt;p>O canal no Telegram não foi criado como fórum técnico de Go. A ideia inicial era ter um espaço administrativo para organizar materiais, temas e decisões do grupo. O principal fórum de Go em português continua sendo o @go_br, mantido por Jeff Otoni.&lt;/p>
&lt;p>Criar canais separados para organização de assuntos é uma prática comum, especialmente para quem já utilizou listas de discussão.&lt;/p>
&lt;p>Na prática, porém, ocorreu o previsível: o canal administrativo passou a discutir tudo - inclusive Go. E assim acabamos com dois canais falando sobre os mesmos temas, às vezes até sobre Go. :D&lt;/p></description></item><item><title>Reflexão sobre organização de código</title><link>https://crg.eti.br/pt-br/jnl/2025-11-07t03-40-38-reflexao-sobre-organizacao-de-codigo/</link><pubDate>Fri, 07 Nov 2025 03:36:33 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-11-07t03-40-38-reflexao-sobre-organizacao-de-codigo/</guid><description>&lt;h1 id="reflexão-sobre-organização-de-código">Reflexão sobre organização de código&lt;/h1>
&lt;p>Há uma reflexão interessante sobre como organizar o código.&lt;/p>
&lt;p>Faz muito tempo que deixei de me preocupar com estruturas de diretórios, tamanhos de arquivos ou localização física do código. Isso porque minha organização não depende da estrutura no disco, mas sim da própria estrutura da linguagem - pacotes, funções e módulos. Além disso, uso ferramentas que me levam diretamente ao ponto do código que quero editar.&lt;/p>
&lt;p>Por exemplo, em vez de procurar manualmente por arquivos ou pastas, configurei meu editor para que, ao pressionar &lt;em>Enter&lt;/em> sobre o nome de uma função ou objeto, ele vá diretamente para sua definição, e ao pressionar &lt;em>Backspace&lt;/em>, volte ao ponto anterior. Tenho vários outros atalhos semelhantes, que me permitem navegar pelo código - não pelos arquivos.&lt;/p>
&lt;p>Esse modo de trabalho tem alguns efeitos. Qualquer forma de indireção no código torna a navegação menos fluida, por isso evito o uso de interfaces quando não são realmente necessárias.&lt;/p>
&lt;p>Prefiro navegar pela lógica do código e não pelo sistema de arquivos, pois isso reduz a carga cognitiva durante a escrita e, principalmente, durante a depuração. Há muitos anos estudo maneiras de reduzir essa carga, eliminando distrações e mantendo o foco na tarefa.&lt;/p>
&lt;p>Sistemas de arquivos não são código, nem se transformam em código - são apenas mais uma camada de indireção, e toda indireção tem um custo.&lt;/p>
&lt;p>Esse método funciona bem para mim porque foi moldado para o meu modo de pensar. Outras pessoas têm abordagens diferentes que fazem mais sentido para elas. Ainda assim, percebo que, cada vez mais, bons programadores tendem a organizar-se com base na estrutura do código, e não na estrutura dos arquivos.&lt;/p></description></item><item><title>Habilitar QUIC/HTTP3.</title><link>https://crg.eti.br/pt-br/jnl/2025-10-27t16-44-29-habilitar-quic-http3/</link><pubDate>Mon, 27 Oct 2025 16:39:12 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-10-27t16-44-29-habilitar-quic-http3/</guid><description>&lt;h1 id="habilitar-quichttp3">Habilitar QUIC/HTTP3.&lt;/h1>
&lt;p>Para quem usa o Caddy versão &amp;gt;= 2.6, basta liberar o acesso UDP na porta 443 no firewall do servidor. O Caddy já vem com suporte nativo ao HTTP/3.&lt;/p>
&lt;p>Testei com curl e com alguns navegadores e funcionou perfeitamente.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -I --http3 https://empreendedor.dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Se o navegador não suportar HTTP/3, ele volta para HTTP/2 automaticamente.&lt;/p></description></item><item><title>Git Blame</title><link>https://crg.eti.br/pt-br/jnl/2025-10-26t08-09-15-git-blame/</link><pubDate>Sun, 26 Oct 2025 08:05:16 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-10-26t08-09-15-git-blame/</guid><description>&lt;h1 id="git-blame">Git Blame&lt;/h1>
&lt;p>Git blame para uma linha específica ou um intervalo de linhas em um arquivo.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>git blame -L 102,102 main.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git blame -L 100,110 main.go
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>O resultado será algo como:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>a1b2c3d4 &lt;span style="color:#0550ae">(&lt;/span>Cesar Gimenes 2025-09-10 102&lt;span style="color:#0550ae">)&lt;/span> valor :&lt;span style="color:#0550ae">=&lt;/span> calc&lt;span style="color:#0550ae">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Onde &lt;code>a1b2c3d4&lt;/code> é o hash do commit.&lt;/p>
&lt;p>Para ver o commit completo:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>git show a1b2c3d4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Isso mostrará todas as alterações feitas naquele commit específico.&lt;/p></description></item><item><title>Limpa campo de documento</title><link>https://crg.eti.br/pt-br/jnl/2025-09-12t16-50-42-limpa-campo-de-documento/</link><pubDate>Fri, 12 Sep 2025 16:49:38 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-09-12t16-50-42-limpa-campo-de-documento/</guid><description>&lt;h1 id="limpa-campo-de-documento">Limpa campo de documento&lt;/h1>
&lt;p>Você tem um campo com o CPF ou CNPJ e quer limpar tudo que não for número?&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">func&lt;/span> &lt;span style="color:#6639ba">RemoveNonDigits&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">s&lt;/span> &lt;span style="color:#cf222e">string&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#cf222e">string&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">var&lt;/span> &lt;span style="color:#1f2328">r&lt;/span> &lt;span style="color:#cf222e">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">for&lt;/span> &lt;span style="color:#1f2328">_&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">c&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#cf222e">range&lt;/span> &lt;span style="color:#1f2328">s&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">if&lt;/span> &lt;span style="color:#1f2328">unicode&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">IsDigit&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">c&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">r&lt;/span> &lt;span style="color:#0550ae">+=&lt;/span> &lt;span style="color:#6639ba">string&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">c&lt;/span>&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">return&lt;/span> &lt;span style="color:#1f2328">r&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>PostgreSQL: Subselect para array</title><link>https://crg.eti.br/pt-br/jnl/2025-09-05t01-47-59-postgresql-subselect-para-array/</link><pubDate>Fri, 05 Sep 2025 01:43:44 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-09-05t01-47-59-postgresql-subselect-para-array/</guid><description>&lt;h1 id="postgresql-subselect-para-array">PostgreSQL: Subselect para array&lt;/h1>
&lt;p>Para criar um array a partir de um subselect em PostgreSQL use a função &lt;code>ARRAY&lt;/code> junto com &lt;code>COALESCE&lt;/code> para garantir que o resultado seja um array vazio caso não haja resultados.&lt;/p>
&lt;p>Exemplo:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">SELECT&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>id&lt;span style="color:#1f2328">,&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">...,&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>coalesce&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#6639ba">ARRAY&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">SELECT&lt;/span>&lt;span style="color:#fff"> &lt;/span>t2&lt;span style="color:#1f2328">.&lt;/span>some_field&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">from&lt;/span>&lt;span style="color:#fff"> &lt;/span>table2&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">as&lt;/span>&lt;span style="color:#fff"> &lt;/span>t2&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">where&lt;/span>&lt;span style="color:#fff"> &lt;/span>t1&lt;span style="color:#1f2328">.&lt;/span>id&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#fff"> &lt;/span>t2&lt;span style="color:#1f2328">.&lt;/span>t1_id&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#1f2328">),&lt;/span>&lt;span style="color:#0a3069">&amp;#39;{}&amp;#39;&lt;/span>&lt;span style="color:#1f2328">::&lt;/span>&lt;span style="color:#6639ba">text&lt;/span>&lt;span style="color:#1f2328">[])&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">as&lt;/span>&lt;span style="color:#fff"> &lt;/span>array_field&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">FROM&lt;/span>&lt;span style="color:#fff"> &lt;/span>table1&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">as&lt;/span>&lt;span style="color:#fff"> &lt;/span>t1&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Neste exemplo, &lt;code>array_field&lt;/code> será um array contendo os valores de &lt;code>some_field&lt;/code> da &lt;code>table2&lt;/code> relacionados ao &lt;code>id&lt;/code> da &lt;code>table1&lt;/code>. Se não houver correspondências, o campo será um array vazio (&lt;code>'{}'::text[]&lt;/code>).&lt;/p></description></item><item><title>The most effective debugging tool</title><link>https://crg.eti.br/pt-br/jnl/2025-08-30t08-03-57-the-most-effective-debugging-tool/</link><pubDate>Sat, 30 Aug 2025 08:02:24 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-08-30t08-03-57-the-most-effective-debugging-tool/</guid><description>&lt;h1 id="the-most-effective-debugging-tool">The most effective debugging tool&lt;/h1>
&lt;p>The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.&lt;/p>
&lt;ul>
&lt;li>Brian W. Kernighan, in the paper Unix for Beginners (1979)&lt;/li>
&lt;/ul></description></item><item><title>len no Bash</title><link>https://crg.eti.br/pt-br/jnl/2025-08-26t14-45-37-len-no-bash/</link><pubDate>Tue, 26 Aug 2025 14:39:24 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-08-26t14-45-37-len-no-bash/</guid><description>&lt;h1 id="len-no-bash">len no Bash&lt;/h1>
&lt;p>Script Bash para retornar o tamanho de uma string, muito útil para uso rápido no terminal.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">&lt;/span>&lt;span style="color:#57606a"># Description: Get the length of a string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"># Usage: len &amp;lt;string&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"># Example: len &amp;#34;hello world&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"># Output: 11&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">set&lt;/span> -euo pipefail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0550ae">[&lt;/span> &lt;span style="color:#0a3069">&amp;#34;&lt;/span>&lt;span style="color:#953800">$#&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&lt;/span> -ne &lt;span style="color:#0550ae">1&lt;/span> &lt;span style="color:#0550ae">]&lt;/span> &lt;span style="color:#0550ae">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#0550ae">{&lt;/span> &lt;span style="color:#6639ba">echo&lt;/span> &lt;span style="color:#0a3069">&amp;#34;Usage: len &amp;lt;string&amp;gt;&amp;#34;&lt;/span> &amp;gt;&lt;span style="color:#1f2328">&amp;amp;&lt;/span>2&lt;span style="color:#1f2328">;&lt;/span> &lt;span style="color:#6639ba">exit&lt;/span> 1&lt;span style="color:#1f2328">;&lt;/span> &lt;span style="color:#0550ae">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">printf&lt;/span> &lt;span style="color:#0a3069">&amp;#39;%d\n&amp;#39;&lt;/span> &lt;span style="color:#0a3069">&amp;#34;&lt;/span>&lt;span style="color:#0a3069">${#&lt;/span>&lt;span style="color:#953800">1&lt;/span>&lt;span style="color:#0a3069">}&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Como verificar seu ipv6</title><link>https://crg.eti.br/pt-br/jnl/2025-08-26t14-34-49-como-verificar-seu-ipv6/</link><pubDate>Tue, 26 Aug 2025 14:33:33 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-08-26t14-34-49-como-verificar-seu-ipv6/</guid><description>&lt;h1 id="como-verificar-seu-ipv6">Como verificar seu ipv6&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -6 https://ifconfig.co
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl -6 https://ipv6.icanhazip.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Configuração do Bash</title><link>https://crg.eti.br/pt-br/jnl/2025-08-10t21-23-58-configuracao-do-bash/</link><pubDate>Sun, 10 Aug 2025 21:17:55 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-08-10t21-23-58-configuracao-do-bash/</guid><description>&lt;h1 id="configuração-do-bash">Configuração do Bash&lt;/h1>
&lt;p>Algumas configurações úteis para adicionar no início de scripts Bash:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">set&lt;/span> -e &lt;span style="color:#57606a"># Exit on error&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">set&lt;/span> -u &lt;span style="color:#57606a"># Treat unset variables as an error&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">set&lt;/span> -x &lt;span style="color:#57606a"># Print commands and their arguments as they are executed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">set&lt;/span> -o pipefail &lt;span style="color:#57606a"># Fail on pipe errors&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ou tudo em uma linha:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">set&lt;/span> -euxo pipefail
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Com isso, você garante:
   &lt;/p>
&lt;ul>
&lt;li>O script falha imediatamente se um comando falhar.&lt;/li>
&lt;li>Variáveis não definidas causam erro.&lt;/li>
&lt;li>Comandos e argumentos são impressos no terminal.&lt;/li>
&lt;li>Erros em pipes são capturados.&lt;/li>
&lt;/ul></description></item><item><title>AGENTS.md</title><link>https://crg.eti.br/pt-br/jnl/2025-08-10t12-11-07-agents-md/</link><pubDate>Sun, 10 Aug 2025 12:04:16 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-08-10t12-11-07-agents-md/</guid><description>&lt;h1 id="agentsmd">AGENTS.md&lt;/h1>
&lt;p>Uma dica para tornar o uso de &lt;code>agents&lt;/code> menos sofrido é criar um arquivo &lt;code>AGENTS.md&lt;/code> na raiz do seu projeto. E colocar nele as informações e contextos que você quer que o agente siga, exemplos de comandos, descrições de tarefas, etc.&lt;/p>
&lt;p>Alguns sistemas já leem esse arquivo automaticamente, mas você pode garantir isso simplesmente solicitando para o agente ler o arquivo e seguir as instruções.&lt;/p>
&lt;p>Exemplos de AGENTS.md em &lt;a href="https://agentsmd.net">https://agentsmd.net&lt;/a>&lt;/p></description></item><item><title>Redirecionando a saída do terminal.</title><link>https://crg.eti.br/pt-br/jnl/2025-07-31t09-58-25-redirecionando-a-saida-do-terminal/</link><pubDate>Thu, 31 Jul 2025 09:51:11 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-31t09-58-25-redirecionando-a-saida-do-terminal/</guid><description>&lt;h1 id="redirecionando-a-saída-do-terminal">Redirecionando a saída do terminal.&lt;/h1>
&lt;p>Você pode redirecionar toda a saída de um &lt;code>script&lt;/code> para um arquivo usando um único comando no início do &lt;code>script&lt;/code>.&lt;/p>
&lt;p>Nesse exemplo, a saída do comando &lt;code>ls&lt;/code> será direcionada para o arquivo &lt;code>out.txt&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">&lt;/span>&lt;span style="color:#6639ba">exec&lt;/span> &amp;gt;out.txt 2&amp;gt;&lt;span style="color:#1f2328">&amp;amp;&lt;/span>&lt;span style="color:#0550ae">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ls -al --color
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Você também pode redirecionar a saída para o console, usando &lt;code>/dev/console&lt;/code>, requer permissão de &lt;code>root&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">&lt;/span>&lt;span style="color:#6639ba">exec&lt;/span> &amp;gt;/dev/console 2&amp;gt;&lt;span style="color:#1f2328">&amp;amp;&lt;/span>&lt;span style="color:#0550ae">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ls -al --color
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>O parâmetro &lt;code>--color&lt;/code> é usado para manter a saída colorida, porque o comando &lt;code>ls&lt;/code> detecta se a saída é um terminal ou não, e ajusta a saída de acordo.&lt;/p></description></item><item><title>Baytimetro</title><link>https://crg.eti.br/pt-br/jnl/2025-07-28t09-39-11-baytimetro/</link><pubDate>Mon, 28 Jul 2025 09:30:20 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-28t09-39-11-baytimetro/</guid><description>&lt;h1 id="baytimetro">Baytimetro&lt;/h1>
&lt;p>Esse fim de semana fiz algumas brincadeiras com o terminal, desenhando direto e recriei um recurso lá dos anos 80 que, apesar de extremamente simples, é muito útil: o baytimetro.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">echo&lt;/span> &lt;span style="color:#0a3069">&amp;#34;12345678901234567890123456789012345678901234567890123456789012345678901234567890&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">echo&lt;/span> &lt;span style="color:#0a3069">&amp;#34; 1 2 3 4 5 6 7 8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ótimo chamar com seu desenho de tela e descobrir se você precisa colocar algum caractere mais para a direita ou esquerda.&lt;/p>
&lt;p>É ridiculamente simples, mas fazer esse tipo de coisa tem um apelo nostálgico muito grande para mim.&lt;/p></description></item><item><title>Função `toclip`</title><link>https://crg.eti.br/pt-br/jnl/2025-07-22t08-27-10-funcao-toclip/</link><pubDate>Tue, 22 Jul 2025 08:20:02 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-22t08-27-10-funcao-toclip/</guid><description>&lt;h1 id="função-toclip">Função &lt;code>toclip&lt;/code>&lt;/h1>
&lt;p>Esta é uma função Bash que uso como parte de meus scripts e ambientes de desenvolvimento. Ela copia o conteúdo do stdin para a área de transferência. Muito útil quando você está acessando um servidor via SSH.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>toclip&lt;span style="color:#0550ae">()&lt;/span> &lt;span style="color:#0550ae">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">[[&lt;/span> &lt;span style="color:#0a3069">${&lt;/span>&lt;span style="color:#953800">SSH_CONNECTION&lt;/span>&lt;span style="color:#1f2328">-&lt;/span>&lt;span style="color:#0a3069">}${&lt;/span>&lt;span style="color:#953800">SSH_TTY&lt;/span>&lt;span style="color:#1f2328">-&lt;/span>&lt;span style="color:#0a3069">}&lt;/span> &lt;span style="color:#0550ae">]]&lt;/span> &lt;span style="color:#0550ae">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#0550ae">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6639ba">printf&lt;/span> &lt;span style="color:#0a3069">$&amp;#39;\033]52;c;%s\a&amp;#39;&lt;/span> &lt;span style="color:#0a3069">&amp;#34;&lt;/span>&lt;span style="color:#cf222e">$(&lt;/span>base64 -w0 2&amp;gt;/dev/null &lt;span style="color:#0550ae">||&lt;/span> base64 &lt;span style="color:#1f2328">|&lt;/span> tr -d &lt;span style="color:#0a3069">&amp;#39;\n&amp;#39;&lt;/span>&lt;span style="color:#cf222e">)&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">case&lt;/span> &lt;span style="color:#953800">$OSTYPE&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> darwin*&lt;span style="color:#0550ae">)&lt;/span> pbcopy &lt;span style="color:#1f2328">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> linux*&lt;span style="color:#0550ae">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">#command -v wl-copy &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&amp;amp; wl-copy &amp;amp;&amp;amp; return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6639ba">command&lt;/span> -v xclip &amp;gt;/dev/null 2&amp;gt;&lt;span style="color:#1f2328">&amp;amp;&lt;/span>&lt;span style="color:#0550ae">1&lt;/span> &lt;span style="color:#0550ae">&amp;amp;&amp;amp;&lt;/span> xclip -selection clipboard &lt;span style="color:#0550ae">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#cf222e">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a"># Fallback Linux without xclip or wl-copy returns to OSC52&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6639ba">printf&lt;/span> &lt;span style="color:#0a3069">$&amp;#39;\033]52;c;%s\a&amp;#39;&lt;/span> &lt;span style="color:#0a3069">&amp;#34;&lt;/span>&lt;span style="color:#cf222e">$(&lt;/span>base64 -w0 2&amp;gt;/dev/null &lt;span style="color:#0550ae">||&lt;/span> base64 &lt;span style="color:#1f2328">|&lt;/span> tr -d &lt;span style="color:#0a3069">&amp;#39;\n&amp;#39;&lt;/span>&lt;span style="color:#cf222e">)&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0550ae">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="exemplo-de-uso">Exemplo de uso&lt;/h2>
&lt;p>Direto do stdin:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">echo&lt;/span> &lt;span style="color:#0a3069">&amp;#34;Texto para copiar&amp;#34;&lt;/span> &lt;span style="color:#1f2328">|&lt;/span> toclip
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Copiando o conteúdo de um arquivo:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>toclip &amp;lt; arquivo.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Listando servidores DNS</title><link>https://crg.eti.br/pt-br/jnl/2025-07-20t09-07-55-listando-servidores-dns/</link><pubDate>Sun, 20 Jul 2025 09:01:03 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-20t09-07-55-listando-servidores-dns/</guid><description>&lt;h1 id="listando-servidores-dns">Listando servidores DNS&lt;/h1>
&lt;p>Para listar os servidores DNS usados no macOS:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>scutil --dns
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Útil para saber quais servidores foram pegos depois de renovar o DHCP.&lt;/p></description></item><item><title>Não largue o osso</title><link>https://crg.eti.br/pt-br/jnl/2025-07-20t01-25-04-nao-largue-o-osso/</link><pubDate>Sun, 20 Jul 2025 01:20:10 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-20t01-25-04-nao-largue-o-osso/</guid><description>&lt;h1 id="não-largue-o-osso">Não largue o osso&lt;/h1>
&lt;p>Uma vez, meu tio William me contou uma história de um piloto de corrida que estava com ele e ia passar por uma curva com uma leve subida. Enquanto tangenciava a curva perfeitamente, em um único e contínuo movimento, reduziu a marcha e acelerou, ao mesmo tempo, virou a fita no toca-fitas. Sem trancos, com o carro ganhando somente a potência necessária. Fez tudo isso como se não fosse nada, enquanto conversava.&lt;/p>
&lt;p>Meu tio usou essa história para me falar sobre preparo e sobre conhecer bem sua profissão. Essa habilidade não vem do nada, não é inata; vem de trabalho duro e determinação.&lt;/p>
&lt;p>Para quem está lendo isso hoje, várias décadas depois, é difícil explicar a complexidade dessa manobra, naquele tempo de câmbios manuais e carburadores mecânicos. Principalmente se você não souber operar um toca-fitas.&lt;/p>
&lt;p>Sinto falta dessas conversas com ele. Gostaria de ter assistido a mais corridas ao seu lado.&lt;/p>
&lt;p>Nas palavras do Sr. William: &lt;em>– Não largue o osso.&lt;/em>&lt;/p></description></item><item><title>n8n com padman</title><link>https://crg.eti.br/pt-br/jnl/2025-07-19t15-15-01-n8n-com-padman/</link><pubDate>Sat, 19 Jul 2025 15:09:54 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-19t15-15-01-n8n-com-padman/</guid><description>&lt;h1 id="n8n-com-padman">n8n com padman&lt;/h1>
&lt;p>Tenho uma máquina que só tem uma regra: tudo que for executado nela deve ser feito em um &lt;code>container&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"># podman volume create n8n_data 2&amp;gt;/dev/null || true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>podman run -it --rm &lt;span style="color:#0a3069">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069">&lt;/span> --name n8n &lt;span style="color:#0a3069">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069">&lt;/span> -p 5678:5678 &lt;span style="color:#0a3069">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069">&lt;/span> -v n8n_data:/home/node/.n8n &lt;span style="color:#0a3069">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069">&lt;/span> -e &lt;span style="color:#953800">N8N_RUNNERS_ENABLED&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#6639ba">true&lt;/span> &lt;span style="color:#0a3069">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069">&lt;/span> -e &lt;span style="color:#953800">N8N_SECURE_COOKIE&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#6639ba">false&lt;/span> &lt;span style="color:#0a3069">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069">&lt;/span> -e &lt;span style="color:#953800">N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#6639ba">true&lt;/span> &lt;span style="color:#0a3069">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069">&lt;/span> docker.n8n.io/n8nio/n8n
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Ajustes para rodar o n8n na rede interna</title><link>https://crg.eti.br/pt-br/jnl/2025-07-18t07-14-17-ajustes-para-rodar-o-n8n-na-rede-interna/</link><pubDate>Fri, 18 Jul 2025 07:10:41 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-18t07-14-17-ajustes-para-rodar-o-n8n-na-rede-interna/</guid><description>&lt;h1 id="ajustes-para-rodar-o-n8n-na-rede-interna">Ajustes para rodar o n8n na rede interna&lt;/h1>
&lt;p>Essas configurações são para rede interna, maquina não acessível pela internet, sem SSL. Use apenas em ambiente de desenvolvimento ou teste.&lt;/p>
&lt;p>Diminui as permissões do arquivo de configuração do n8n.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>chmod &lt;span style="color:#0550ae">600&lt;/span> /home/user/.n8n/config
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Rodando na rede interna sem SSL e com task runners habilitados:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">export&lt;/span> &lt;span style="color:#953800">N8N_RUNNERS_ENABLED&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#6639ba">true&lt;/span> &lt;span style="color:#57606a">#enable task runners&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#6639ba">export&lt;/span> &lt;span style="color:#953800">N8N_SECURE_COOKIE&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#6639ba">false&lt;/span> &lt;span style="color:#57606a">#disable secure cookies&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>npx n8n
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Listar variáveis</title><link>https://crg.eti.br/pt-br/jnl/2025-07-17t15-39-22-listar-variaveis/</link><pubDate>Thu, 17 Jul 2025 15:37:41 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-17t15-39-22-listar-variaveis/</guid><description>&lt;h1 id="listar-variáveis">Listar variáveis&lt;/h1>
&lt;p>Tecnica para fazer &amp;ldquo;debug de pobre&amp;rdquo; em Lua, listando variáveis globais e locais.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-lua" data-lang="lua">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">-- List all global variables&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">for&lt;/span> name&lt;span style="color:#1f2328">,&lt;/span> value &lt;span style="color:#cf222e">in&lt;/span> pairs&lt;span style="color:#1f2328">(&lt;/span>_G&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#cf222e">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> repr &lt;span style="color:#0550ae">=&lt;/span> tostring&lt;span style="color:#1f2328">(&lt;/span>value&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print&lt;span style="color:#1f2328">(&lt;/span>string.format&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;%s = %s&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> name&lt;span style="color:#1f2328">,&lt;/span> repr&lt;span style="color:#1f2328">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-lua" data-lang="lua">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">-- List all local variables in the current function&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">-- This will only work if the code is run in a function context&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">local&lt;/span> &lt;span style="color:#cf222e">function&lt;/span> &lt;span style="color:#6639ba">list_locals&lt;/span>&lt;span style="color:#1f2328">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> i &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#0550ae">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">while&lt;/span> &lt;span style="color:#cf222e">true&lt;/span> &lt;span style="color:#cf222e">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> var_name&lt;span style="color:#1f2328">,&lt;/span> var_value &lt;span style="color:#0550ae">=&lt;/span> debug.getlocal&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0550ae">2&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> i&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">if&lt;/span> &lt;span style="color:#0550ae">not&lt;/span> var_name &lt;span style="color:#cf222e">then&lt;/span> &lt;span style="color:#cf222e">break&lt;/span> &lt;span style="color:#cf222e">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print&lt;span style="color:#1f2328">(&lt;/span>string.format&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;%s = %s&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> var_name&lt;span style="color:#1f2328">,&lt;/span> tostring&lt;span style="color:#1f2328">(&lt;/span>var_value&lt;span style="color:#1f2328">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> i &lt;span style="color:#0550ae">=&lt;/span> i &lt;span style="color:#0550ae">+&lt;/span> &lt;span style="color:#0550ae">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">-- Example&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">local&lt;/span> &lt;span style="color:#cf222e">function&lt;/span> &lt;span style="color:#6639ba">demo&lt;/span>&lt;span style="color:#1f2328">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> a &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#0550ae">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> b &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#0a3069">&amp;#34;hello&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> list_locals&lt;span style="color:#1f2328">()&lt;/span> &lt;span style="color:#57606a">-- This will list local variables a and b&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>demo&lt;span style="color:#1f2328">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Conway's Game of Life</title><link>https://crg.eti.br/pt-br/jnl/2025-07-17t09-26-32-essa-noite-de-brincadeira-criei-uma-versao-para-terminal-do-consagrado-jogo-da-vida-de-conway-conway-s-game-of-life/</link><pubDate>Thu, 17 Jul 2025 09:22:34 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-17t09-26-32-essa-noite-de-brincadeira-criei-uma-versao-para-terminal-do-consagrado-jogo-da-vida-de-conway-conway-s-game-of-life/</guid><description>&lt;h1 id="conways-game-of-life">Conway&amp;rsquo;s Game of Life&lt;/h1>
&lt;p>Essa noite de brincadeira, criei uma versão para terminal do consagrado Jogo da Vida de Conway (Conway&amp;rsquo;s Game of Life).&lt;/p>
&lt;figure class="media-frame media-center fade-in">&lt;img alt="life" src="https://raw.githubusercontent.com/crgimenes/life/refs/heads/trunk/life.webp" loading="lazy" decoding="async">&lt;/figure>&lt;p>&lt;a href="https://github.com/crgimenes/life">https://github.com/crgimenes/life&lt;/a>&lt;/p></description></item><item><title>Sobre tentar manter um diário: Se eu não escrever o que tenho na cabeça imediatamente, provavelmente eu nunca vou escrever.</title><link>https://crg.eti.br/pt-br/jnl/2025-07-16t22-20-27-sobre-tentar-manter-um-diario-se-eu-nao-escrever-o-que-tenho-na-cabeca-imediatamente-provavelmente-eu-nunca-vou-escrever/</link><pubDate>Wed, 16 Jul 2025 22:20:06 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-16t22-20-27-sobre-tentar-manter-um-diario-se-eu-nao-escrever-o-que-tenho-na-cabeca-imediatamente-provavelmente-eu-nunca-vou-escrever/</guid><description>&lt;p>Sobre tentar manter um diário: Se eu não escrever o que tenho na cabeça imediatamente, provavelmente eu nunca vou escrever.&lt;/p></description></item><item><title>Processamento de Registros em Lote com PostgreSQL e Go</title><link>https://crg.eti.br/pt-br/jnl/2025-07-07t17-19-52-processamento-de-registros-em-lote-com-postgresql-e-go/</link><pubDate>Mon, 07 Jul 2025 17:19:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/jnl/2025-07-07t17-19-52-processamento-de-registros-em-lote-com-postgresql-e-go/</guid><description>&lt;h1 id="processamento-de-registros-em-lote-com-postgresql-e-go">Processamento de Registros em Lote com PostgreSQL e Go&lt;/h1>
&lt;p>Este é um padrão interessante para processamento de registros em lote no Go com PostgreSQL. Ele utiliza transações e bloqueios para garantir que os registros sejam processados de forma segura e eficiente, evitando conflito entre múltiplas instâncias do processo.&lt;/p>
&lt;p>O truque é combinar o uso de &lt;code>FOR UPDATE SKIP LOCKED&lt;/code> para evitar que múltiplas instâncias do processo leiam e processem o mesmo registro ao mesmo tempo, e o uso do índice (id) para evitar que algum erro de processamento faça com que o registro seja processado novamente porque não houve uma mudança de status.&lt;/p>
&lt;p>Se houver um erro durante o processamento, o registro não é atualizado e permanece com o status &amp;lsquo;pendente&amp;rsquo;. Sem o &lt;code>WHERE id &amp;gt; $1&lt;/code>, o loop poderia entrar em um ciclo infinito tentando processar o mesmo registro repetidamente.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">var&lt;/span> &lt;span style="color:#1f2328">id&lt;/span> &lt;span style="color:#cf222e">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">for&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">done&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#cf222e">func&lt;/span>&lt;span style="color:#1f2328">()&lt;/span> &lt;span style="color:#cf222e">bool&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">const&lt;/span> &lt;span style="color:#1f2328">sqlStatement&lt;/span> &lt;span style="color:#1f2328">=&lt;/span> &lt;span style="color:#0a3069">`SELECT
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069"> id, ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069"> FROM ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069"> WHERE id &amp;gt; $1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069"> AND status = &amp;#39;pendente&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069"> AND ...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069"> ORDER BY id
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#0a3069"> FOR UPDATE SKIP LOCKED LIMIT 1;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// aqui inicia uma transação&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">tx&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#0550ae">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">defer&lt;/span> &lt;span style="color:#cf222e">func&lt;/span>&lt;span style="color:#1f2328">()&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// mecanismo de rollback&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// então executa a consulta&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#1f2328">tx&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">QueryRow&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">sqlStatement&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">id&lt;/span>&lt;span style="color:#1f2328">).&lt;/span>&lt;span style="color:#6639ba">Scan&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0550ae">&amp;amp;&lt;/span>&lt;span style="color:#1f2328">id&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#0550ae">...&lt;/span>&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">if&lt;/span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#0550ae">!=&lt;/span> &lt;span style="color:#cf222e">nil&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">if&lt;/span> &lt;span style="color:#1f2328">errors&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Is&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">err&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">sql&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">ErrNoRows&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">return&lt;/span> &lt;span style="color:#cf222e">true&lt;/span> &lt;span style="color:#57606a">// não há mais registros&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// trata outros erros&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">return&lt;/span> &lt;span style="color:#cf222e">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// aqui faz o processamento do registro e atualiza o status&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// pode ser fail, paid, processed, etc.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// ...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// se tudo estiver ok, confirma a transação&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#1f2328">=&lt;/span> &lt;span style="color:#1f2328">tx&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Commit&lt;/span>&lt;span style="color:#1f2328">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">if&lt;/span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#0550ae">!=&lt;/span> &lt;span style="color:#cf222e">nil&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#57606a">// trata erro de commit geralmente log.Fatal(...)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">return&lt;/span> &lt;span style="color:#cf222e">false&lt;/span> &lt;span style="color:#57606a">// indica que o loop deve continuar&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">if&lt;/span> &lt;span style="color:#1f2328">done&lt;/span> &lt;span style="color:#1f2328">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">break&lt;/span> &lt;span style="color:#57606a">// não há mais registros para processar&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Este é um exemplo bom para processamento de registros em lote e pode ser tranquilamente colocado para rodar de tempos em tempos, como um cron job, para processar registros pendentes em um banco de dados PostgreSQL.&lt;/p>
&lt;p>Uma vantagem interessante é que, se o processamento demorar muito, automaticamente o cron vai carregar outras instâncias do processo, que vão pegar os registros que ainda não foram processados e não estão bloqueados (SKIP LOCKED). Isso permite que o sistema escale horizontalmente, processando mais registros em paralelo sem risco de conflitos.&lt;/p></description></item></channel></rss>