<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Meus artigos e tutoriais de programação on Cesar Gimenes</title><link>https://crg.eti.br/pt-br/pub/</link><description>Recent content in Meus artigos e tutoriais de programação on 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>Thu, 20 Jun 2019 01:30:36 -0200</lastBuildDate><atom:link href="https://crg.eti.br/pt-br/pub/index.xml" rel="self" type="application/rss+xml"/><item><title>Kutta no navegador: mesmo código, outro orçamento de frame</title><link>https://crg.eti.br/pt-br/pub/kutta-no-navegador/</link><pubDate>Sun, 16 Aug 2026 10:30:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/kutta-no-navegador/</guid><description>&lt;p>O &lt;a href="https://crg.eti.br/pt-br/pub/kutta/">Kutta&lt;/a> agora roda dentro de uma aba do navegador. Mesmo código do desktop, &lt;code>GOOS=js GOARCH=wasm&lt;/code>, nenhum fork, nenhum arquivo duplicado com uma versão &amp;ldquo;web&amp;rdquo; do solver.&lt;/p>
&lt;figure class="media-frame media-center fade-in media-gif">
&lt;a href="https://crgimenes.itch.io/kutta">&lt;img alt="Kutta soltando vórtices a 20 graus de ângulo de ataque" src="https://crg.eti.br/pub/kutta-no-navegador/vortices.webp" height="560" width="800" loading="lazy" decoding="async">&lt;/a>
&lt;/figure>
&lt;p>O que não é de graça é a velocidade. Um passo do solver custa &lt;strong>6,1 ms no wasm contra 2,3 ms nativo&lt;/strong>, medido no grid de 360x200 que o app usa, num Mac M4, com o mesmo solver compilado para os dois alvos na mesma máquina. Fator 2,6.&lt;/p></description></item><item><title>Kutta, um pequeno túnel de vento em Go</title><link>https://crg.eti.br/pt-br/pub/kutta/</link><pubDate>Wed, 08 Jul 2026 00:30:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/kutta/</guid><description>&lt;p>Dá pra explicar sustentação com um diagrama e uma equação. Quase nunca gruda. Ver a esteira descolar da traseira de uma asa enquanto você gira o ângulo de ataque gruda na hora. É essa distância que faz o &lt;strong>Kutta&lt;/strong> existir.&lt;/p>
&lt;p>É um pequeno túnel de vento 2D escrito em Go, renderizado com &lt;a href="https://ebitengine.org">Ebitengine&lt;/a>, rodando como um único aplicativo desktop.&lt;/p>
&lt;figure class="media-frame media-center fade-in media-gif">
&lt;a href="https://github.com/crgimenes/kutta">&lt;img alt="Kutta rodando" src="https://crg.eti.br/pub/kutta/kutta.webp" height="338" width="600" loading="lazy" decoding="async">&lt;/a>
&lt;/figure>
&lt;p>A ideia nunca passou do primeiro rascunho: escoar ar por um aerofólio e deixar o escoamento visível. Muda o ângulo de ataque e o campo reage. Alterna entre velocidade, vorticidade e um campo tipo pressão. Desenha sua própria forma. Corta uma asa em asa e flap, anima o flap, e vê a esteira ficar instável quando a geometria ou o ângulo passam do ponto.&lt;/p></description></item><item><title>Glaze, WebView desktop em Go sem CGO</title><link>https://crg.eti.br/pt-br/pub/glaze/</link><pubDate>Mon, 22 Jun 2026 10:15:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/glaze/</guid><description>&lt;p>Abrir uma janela com HTML em Go quase sempre cobra um pedágio em C.&lt;/p>
&lt;p>Ou você liga o cgo e arrasta uma toolchain C pro projeto, ou alguém embute uma &lt;code>.dll&lt;/code>/&lt;code>.so&lt;/code>/&lt;code>.dylib&lt;/code> compilada no binário e extrai em disco na primeira execução. Os dois funcionam. E os dois te tiram justamente o que eu gosto no ecossistema: o &lt;code>go build&lt;/code> que cross-compila pra três sistemas sem pensar, o build reprodutível, o &lt;code>go install&lt;/code> que roda pra quem clonou o repo. É a primeira coisa que vai embora quando o C entra.&lt;/p></description></item><item><title>singleflight em Go</title><link>https://crg.eti.br/pt-br/pub/singleflight/</link><pubDate>Sat, 13 Jun 2026 09:57:41 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/singleflight/</guid><description>&lt;p>Você tem uma função cara e pesada. Em um pico de tráfego chegam seis requisições ao mesmo tempo pedindo exatamente a mesma coisa. Sem nenhum cuidado, você executa esse função seis vezes para obter seis resultados idênticos.&lt;/p>
&lt;p>&lt;strong>singleflight&lt;/strong> é um padrão que colapsa essas chamadas. A primeira chamada para uma chave executa o trabalho de verdade. Todas as outras que chegam &lt;em>enquanto ela está em andamento&lt;/em> ficam esperando e recebem o mesmo resultado. Uma execução, vários consumidores.&lt;/p></description></item><item><title>Text chunker com sobreposição para pipelines RAG</title><link>https://crg.eti.br/pt-br/pub/text_chunker/</link><pubDate>Sat, 06 Jun 2026 11:57:59 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/text_chunker/</guid><description>&lt;p>Em pipeline de RAG (&lt;em>Retrieval-Augmented Generation&lt;/em>) o primeiro passo é quase sempre o mesmo: pegar um texto grande e quebrar em pedaços antes de vetorizar. Os pedaços não podem ser grandes demais, porque o modelo tem limite de contexto, nem pequenos demais, porque aí o embedding perde semântica. E precisam ter sobreposição entre vizinhos, senão uma resposta que cai bem na fronteira fica espremida entre dois chunks e o retriever erra.&lt;/p></description></item><item><title>Um cofre cifrado em Go</title><link>https://crg.eti.br/pt-br/pub/cofre-cifrado-em-go/</link><pubDate>Sun, 31 May 2026 01:02:01 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/cofre-cifrado-em-go/</guid><description>&lt;p>Vamos juntar as três peças anteriores:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://crg.eti.br/pt-br/pub/capturando-senhas-no-terminal-go/">senha no terminal&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://crg.eti.br/pt-br/pub/criptografia-at-rest-com-a-stdlib-go/">criptografia at rest&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://crg.eti.br/pt-br/pub/sqlite-na-ram-serialize-deserialize/">snapshot do SQLite&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Um banco SQLite que vive na RAM e, no disco existe apenas como um blob criptografado.&lt;/p>
&lt;p>O banco roda em &lt;code>:memory:&lt;/code>.
Ao sair, tiramos o &lt;em>snapshot&lt;/em> dos bytes do banco, criptografamos com a senha e gravamos.
Ao entrar, lemos o blob, decriptamos com a senha e fazemos o &lt;em>deserialize&lt;/em> de volta para a RAM.&lt;/p>
&lt;p>Aqui a proteção dos dados depende da força da senha, e do algoritmo de criptografia (aqui, AES-GCM). Precisa tomar cuidado com o tamanho do banco porque fazer o dump, criptografar e gravar tudo de uma vez pode ser lento. Mas é muito bom para salvar dados sensíveis, como chaves de API, tokens, etc.&lt;/p></description></item><item><title>SQLite na RAM: serialize e deserialize em Go</title><link>https://crg.eti.br/pt-br/pub/sqlite-na-ram-serialize-deserialize/</link><pubDate>Sun, 31 May 2026 00:46:31 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/sqlite-na-ram-serialize-deserialize/</guid><description>&lt;p>O SQLite pode rodar inteiramente na memória, sem nunca tocar o disco. E tem um truque pouco conhecido: dá para tirar um &lt;em>snapshot&lt;/em> dos bytes do próprio banco e recarregá-lo depois, sem &lt;code>INSERT&lt;/code>, sem reconstruir nada. As funções são &lt;code>sqlite3_serialize&lt;/code> e &lt;code>sqlite3_deserialize&lt;/code>.&lt;/p>
&lt;p>Vou usar o driver &lt;code>modernc.org/sqlite&lt;/code>, que é Go puro, sem CGo.&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:#1f2328">db&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#1f2328">sql&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Open&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;sqlite&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#0a3069">&amp;#34;:memory:&amp;#34;&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:#6639ba">fatal&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>&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">db&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">SetMaxOpenConns&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0550ae">1&lt;/span>&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A pegadinha está no &lt;code>SetMaxOpenConns(1)&lt;/code>. Um banco &lt;code>:memory:&lt;/code> pertence à conexão que o abriu. Sem limitar a uma conexão, o pool do &lt;code>database/sql&lt;/code> poderia abrir outra e essa veria um banco vazio e diferente.&lt;/p></description></item><item><title>Criptografia at rest com a stdlib do Go</title><link>https://crg.eti.br/pt-br/pub/criptografia-at-rest-com-a-stdlib-go/</link><pubDate>Sun, 31 May 2026 00:38:32 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/criptografia-at-rest-com-a-stdlib-go/</guid><description>&lt;p>Quero guardar um dado no disco de forma que, mesmo que o arquivo vaze, ele só seja legível com a senha e que qualquer adulteração seja detectada.&lt;/p>
&lt;p>Para isso vamos proteger os dados criptografando ele &amp;ldquo;at rest&amp;rdquo; o que basicamente significa que os dados estão protegidos quando são salvos no disco, e só podem ser acessados por quem tem a senha correta.&lt;/p>
&lt;p>Dá para fazer isso só com a biblioteca padrão:&lt;/p></description></item><item><title>Capturando senhas no terminal com Go</title><link>https://crg.eti.br/pt-br/pub/capturando-senhas-no-terminal-go/</link><pubDate>Sat, 30 May 2026 10:00:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/capturando-senhas-no-terminal-go/</guid><description>&lt;p>Ler uma senha no terminal parece trivial, mas tem duas armadilhas: a senha aparece na tela se você usar a leitura comum, e você precisa garantir que é realmente um terminal e não redirecionamento. Vamos resolver as duas com o pacote &lt;code>golang.org/x/term&lt;/code>.&lt;/p>
&lt;p>Se você ler com &lt;code>bufio.Scanner&lt;/code> ou &lt;code>fmt.Scanln&lt;/code>, cada tecla aparece na tela. Para senha isso não serve. O &lt;code>term.ReadPassword&lt;/code> lê direto do terminal, sem eco:&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:#1f2328">fd&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#6639ba">int&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">os&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">Stdin&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Fd&lt;/span>&lt;span style="color:#1f2328">())&lt;/span> &lt;span style="color:#57606a">// #nosec G115 -- stdin&amp;#39;s fd is small; the conversion is safe&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#1f2328">fmt&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Print&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;password: &amp;#34;&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">pass&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#1f2328">term&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">ReadPassword&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">fd&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">fmt&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Println&lt;/span>&lt;span style="color:#1f2328">()&lt;/span> &lt;span style="color:#57606a">// the user&amp;#39;s Enter doesn&amp;#39;t emit a newline; we do it&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;a href="https://crg.eti.br/pub/capturando-senhas-no-terminal-go/main.go">código fonte completo em&lt;/a>&lt;/p></description></item><item><title>Neko, um gato perseguindo o mouse com Go e Ebitengine</title><link>https://crg.eti.br/pt-br/pub/neko/</link><pubDate>Sat, 11 Apr 2026 09:15:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/neko/</guid><description>&lt;p>Todo programador devia escrever ao menos um software inútil de propósito.&lt;/p>
&lt;p>Inútil aqui no melhor sentido. Não serve para empresa nenhuma, não vai parar numa reunião de produto e não tem chance de algum gerente pedir integração com webhook. Mesmo assim obriga você a lidar com problemas reais. Tela, input, tempo, sprite, som, janela, sistema operacional. Um brinquedo desses ensina mais sobre software interativo do que muito CRUD com cara de demo corporativa.&lt;/p></description></item><item><title>trigger no SQLite</title><link>https://crg.eti.br/pt-br/pub/trigger-no-sqlite/</link><pubDate>Fri, 03 Oct 2025 23:57:24 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/trigger-no-sqlite/</guid><description>&lt;p>O &lt;em>SQLite&lt;/em> não suporta &lt;em>stored procedure&lt;/em> diretamente, mas suporta &lt;em>triggers&lt;/em> o que é um recurso muito útil para automatizar algumas ações.&lt;/p>
&lt;p>Por exemplo, atualizar automaticamente o campo &lt;code>updated_at&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-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">CREATE&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">TABLE&lt;/span>&lt;span style="color:#fff"> &lt;/span>users&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>id&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#6639ba">INTEGER&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">PRIMARY&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">KEY&lt;/span>&lt;span style="color:#fff"> &lt;/span>AUTOINCREMENT&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>nome&lt;span style="color:#fff"> &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>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff"> &lt;/span>updated_at&lt;span style="color:#fff"> &lt;/span>DATETIME&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">DEFAULT&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">CURRENT_TIMESTAMP&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>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#fff">&lt;/span>&lt;span style="color:#cf222e">CREATE&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">TRIGGER&lt;/span>&lt;span style="color:#fff"> &lt;/span>update_timestamp&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">BEFORE&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">UPDATE&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">ON&lt;/span>&lt;span style="color:#fff"> &lt;/span>users&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">FOR&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">EACH&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">ROW&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">BEGIN&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">UPDATE&lt;/span>&lt;span style="color:#fff"> &lt;/span>users&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">SET&lt;/span>&lt;span style="color:#fff"> &lt;/span>updated_at&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">CURRENT_TIMESTAMP&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">WHERE&lt;/span>&lt;span style="color:#fff"> &lt;/span>id&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#fff"> &lt;/span>&lt;span style="color:#cf222e">OLD&lt;/span>&lt;span style="color:#1f2328">.&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:#cf222e">END&lt;/span>&lt;span style="color:#1f2328">;&lt;/span>&lt;span style="color:#fff">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Agora, quando você atualizar um registro na tabela &lt;code>users&lt;/code>, o campo &lt;code>updated_at&lt;/code> será atualizado automaticamente para o &lt;em>timestamp&lt;/em> atual.&lt;/p></description></item><item><title>Função recursiva em Go para acessar valores em mapas aninhados</title><link>https://crg.eti.br/pt-br/pub/get-from-map/</link><pubDate>Mon, 22 Sep 2025 17:33:43 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/get-from-map/</guid><description>&lt;p>Recentemente, recebi um retorno de uma API que continha um JSON com uma estrutura complexa, grande e aninhada. Eu precisava acessar um valor específico dentro dessa estrutura, mas o caminho para esse valor poderia variar.&lt;/p>
&lt;p>A ideia então foi criar uma função recursiva que recebesse uma lista com o caminho (path) para o valor desejado e a estrutura de dados (um mapa aninhado) e retornasse o valor correspondente, se encontrado.&lt;/p></description></item><item><title>Subindo serviços com /etc/rc.local como nos anos 80</title><link>https://crg.eti.br/pt-br/pub/etc-rc-local/</link><pubDate>Sun, 20 Jul 2025 14:19:38 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/etc-rc-local/</guid><description>&lt;p>Costumo usar o &lt;em>script&lt;/em> &lt;code>/etc/rc.local&lt;/code> para subir serviços rapidamente durante o boot. É conveniente, simples e funciona bem no Debian e em outras distribuições Linux. Basicamente, é apenas um script sh (ou o shell que você preferir) que é executado durante o boot.&lt;/p>
&lt;p>Curiosamente, o &lt;em>rc.local&lt;/em> é considerado obsoleto desde o lançamento do &lt;em>UNIX System III&lt;/em>, em 1983!&lt;/p>
&lt;p>Desde então, diversas tentativas foram feitas para descontinuar esse arquivo. Ele não é recomendado há muito tempo em favor de soluções mais modernas para iniciar serviços durante o boot, mas ainda persiste. Se o arquivo &lt;code>/etc/rc.local&lt;/code> não existir no seu sistema, tente criá-lo e dar permissão de execução. Existe uma boa chance de o systemd reconhecer que você é totalmente &lt;em>old school&lt;/em> e executar o &lt;em>rc.local&lt;/em> normalmente durante o &lt;em>boot&lt;/em>, inclusive esperando educadamente a rede ser ativada antes de rodá-lo (testado no Debian e no Ubuntu).&lt;/p></description></item><item><title>sftpdav: Acesso Remoto via SSH com WebDAV</title><link>https://crg.eti.br/pt-br/pub/serve-webdav-with-go/</link><pubDate>Sat, 15 Mar 2025 18:11:26 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/serve-webdav-with-go/</guid><description>&lt;p>Recentemente, enfrentei um desafio ao tentar acessar arquivos de uma máquina que só permite conexão via SSH. Abrir portas adicionais ou instalar extensões de terceiros não eram opções viáveis por questões de segurança e compatibilidade, especialmente no macOS.&lt;/p>
&lt;p>Foi assim que surgiu a ideia de criar o &lt;strong>sftpdav&lt;/strong>, um programa que combina um cliente SFTP com um servidor WebDAV, permitindo acessar um diretório remoto via SSH e montá-lo localmente como se fosse um compartilhamento WebDAV.&lt;/p></description></item><item><title>Protegendo credenciais e configurações com contêiner criptografado.</title><link>https://crg.eti.br/pt-br/pub/protegendo-credenciais-e-configuracoes-com-conteiner-criptografado/</link><pubDate>Thu, 20 Feb 2025 22:43:56 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/protegendo-credenciais-e-configuracoes-com-conteiner-criptografado/</guid><description>&lt;p>Eu uso um pequeno computador de bolso na mochila. Esse dispositivo serve para testes e desenvolvimento, e armazena informações sensíveis como credenciais, senhas e chaves de acesso. Eu não quero que esses dados caiam em mãos erradas. Diferentemente do notebook, que tem o HD criptografado, meu computador de bolso não usa criptografia no HD. A criptografia consome muito processamento e requer desativar o TRIM do SSD, o que prejudica o desempenho.&lt;/p></description></item><item><title>LQS: Uma Ferramenta Prática para Testar e Debugar SQL</title><link>https://crg.eti.br/pt-br/pub/lqs-uma-ferramenta-prtica-para-testar-sql/</link><pubDate>Sat, 15 Feb 2025 18:31:26 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/lqs-uma-ferramenta-prtica-para-testar-sql/</guid><description>&lt;p>É muito comum precisarmos inserir strings com código SQL no fonte de outras linguagens, o problema desse SQL é uma linguagem interpretada e portanto só pode conter erros que só vamos perceber em tempo de execução.&lt;/p>
&lt;h2 id="testando-sql">Testando SQL&lt;/h2>
&lt;p>O LQS foi criado para trabalhar junto com o Neovim e permitir testar o SQL durante a edição, sem copiar e colar para outro arquivo ou cliente SQL.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Testar SQL com metadados embutidos:&lt;/strong>
Insira configurações direto no seu script SQL, como a string de conexão, opção de saída em JSON, ou até mesmo uma query extra para gerar parâmetros.
Exemplo:&lt;/p></description></item><item><title>Ordenando e removendo linhas duplicadas com Neovim</title><link>https://crg.eti.br/pt-br/pub/nvim-sort/</link><pubDate>Sun, 09 Feb 2025 14:32:33 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/nvim-sort/</guid><description>&lt;p>Uma boa organização facilita a leitura do código. Listas desorganizadas dificultam a manutenção do projeto, sem falar que o código fica com um aspecto pouco profissional.&lt;/p>
&lt;p>Estas duas funções ordenam e removem linhas duplicadas em blocos de texto selecionados no &lt;em>Neovim&lt;/em>.&lt;/p>
&lt;p>A função &lt;code>sort_lines&lt;/code> ordena as linhas selecionadas:&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:#cf222e">function&lt;/span> &lt;span style="color:#6639ba">sort_lines&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> start_pos &lt;span style="color:#0550ae">=&lt;/span> vim.fn&lt;span style="color:#1f2328">.&lt;/span>getpos&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&amp;#39;&amp;lt;&amp;#34;&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> end_pos &lt;span style="color:#0550ae">=&lt;/span> vim.fn&lt;span style="color:#1f2328">.&lt;/span>getpos&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&amp;#39;&amp;gt;&amp;#34;&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> start_line &lt;span style="color:#0550ae">=&lt;/span> start_pos&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#0550ae">2&lt;/span>&lt;span style="color:#1f2328">]&lt;/span> &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">local&lt;/span> end_line &lt;span style="color:#0550ae">=&lt;/span> end_pos&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#0550ae">2&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> lines &lt;span style="color:#0550ae">=&lt;/span> vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_buf_get_lines&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">0&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> start_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> end_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&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> table.sort&lt;span style="color:#1f2328">(&lt;/span>lines&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> vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_buf_set_lines&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">0&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> start_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> end_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">false&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> lines
&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">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A função &lt;code>sort_and_uniq_lines&lt;/code> ordena e remove linhas duplicadas:&lt;/p></description></item><item><title>Bookmarks em Neovim</title><link>https://crg.eti.br/pt-br/pub/nvim-bookmarks/</link><pubDate>Sun, 09 Feb 2025 11:52:14 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/nvim-bookmarks/</guid><description>&lt;p>Eu percorro muitos arquivos quando trabalho, principalmente ao resolver bugs ou rastrear comportamentos. Eu criei um sistema de marcadores (bookmarks) no &lt;em>Neovim&lt;/em> para navegar mais rápido entre arquivos. Esse sistema difere do sistema padrão do &lt;em>Neovim&lt;/em>, pois foca em marcar arquivos e linhas, não apenas posições dentro do mesmo arquivo.&lt;/p>
&lt;h2 id="funcionamento">Funcionamento&lt;/h2>
&lt;p>O sistema registra o caminho do arquivo e a linha atual em um arquivo texto. Eu uso a tecla &lt;code>&amp;lt;leader&amp;gt;o&lt;/code> para abrir todos os arquivos marcados. Eu uso a tecla &lt;code>&amp;lt;leader&amp;gt;m&lt;/code> para marcar um arquivo. Eu também uso o comando &lt;code>:Clearmarks&lt;/code> para limpar todos os marcadores quando termino um trabalho ou inicio outro.&lt;/p></description></item><item><title>GoScope Explorando e Navegando em Projetos Go</title><link>https://crg.eti.br/pt-br/pub/goscope-explorando-e-navegando-em-projetos-go/</link><pubDate>Sun, 09 Feb 2025 02:47:39 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/goscope-explorando-e-navegando-em-projetos-go/</guid><description>&lt;p>Muitas vezes, quero analisar rapidamente um projeto Go para entender onde funções, variáveis e tipos estão definidos ou chamados. Foi assim que criei duas ferramentas de linha de comando: &lt;strong>GoScope&lt;/strong> e &lt;strong>rgs&lt;/strong>. A primeira faz um escaneamento completo de todos os arquivos &lt;code>.go&lt;/code> de um projeto, gerando uma lista de definições e chamadas de funções. A segunda usa essa lista para me permitir navegar de forma interativa até o ponto exato do código.&lt;/p></description></item><item><title>Executando Comandos Remotos de Forma Interativa com SSH</title><link>https://crg.eti.br/pt-br/pub/executando-comandos-remotos-de-forma-interativa-com-ssh/</link><pubDate>Sat, 08 Feb 2025 13:38:17 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/executando-comandos-remotos-de-forma-interativa-com-ssh/</guid><description>&lt;p>Muitas vezes, eu preciso executar um comando em um servidor remoto, mas não desejo iniciar uma sessão interativa completa. Quero que o programa mantenha todas as características de um processo local, porém seja executado no servidor remoto.&lt;/p>
&lt;p>Inicialmente, eu apenas usava o comando &lt;code>ssh&lt;/code> especificando o servidor e o comando que desejo executar:&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>ssh servidor comando
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Esse método não funciona bem para programas que exigem um pseudo terminal, como o &lt;em>Neovim&lt;/em>. Para resolver isso, eu tentei a opção &lt;code>-t&lt;/code> para forçar a alocação de um pseudo terminal. Assim, programas como o &lt;code>ls&lt;/code> exibem cores, mas o ambiente de usuário não é carregado. Nesse caso, eu preciso usar a opção &lt;code>--color&lt;/code> no &lt;code>ls&lt;/code>. Mesmo assim, programas como o &lt;em>Neovim&lt;/em> falham porque o &lt;em>shell&lt;/em> não se comporta como interativo e códigos ANSI não são processados corretamente.&lt;/p></description></item><item><title>Traceback em Go: Como Explorar a Pilha de Execução</title><link>https://crg.eti.br/pt-br/pub/tracebacks-em-go/</link><pubDate>Thu, 06 Feb 2025 02:12:46 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/tracebacks-em-go/</guid><description>&lt;p>Muitas linguagens de programação fornecem algum tipo de &amp;ldquo;stack trace&amp;rdquo; ou &amp;ldquo;backtrace&amp;rdquo;. Python usa o módulo &lt;code>traceback&lt;/code>, C no Linux oferece a função &lt;code>backtrace()&lt;/code> em &lt;code>execinfo.h&lt;/code> (não faz parte do padrão do C) e Java inclui &lt;code>Thread.dumpStack()&lt;/code> ou &lt;code>e.printStackTrace()&lt;/code> para exceções.&lt;/p>
&lt;h2 id="stack-trace-em-go">Stack Trace em Go&lt;/h2>
&lt;p>O Go fornece a função &lt;code>runtime.Caller&lt;/code> para obter informações sobre a pilha de execução. O exemplo a seguir exibe o arquivo, a linha e a função que chamaram &lt;code>info()&lt;/code>. Observe que o argumento &lt;code>1&lt;/code> passado para &lt;code>runtime.Caller&lt;/code> indica que queremos informações sobre a função que chamou &lt;code>info()&lt;/code>:&lt;/p></description></item><item><title>Transmissão de Dados Usando Som: Uma Experiência com 'Telefone de Copos'</title><link>https://crg.eti.br/pt-br/pub/transmissao-de-dados-usando-som-via-telefone-de-copos/</link><pubDate>Sat, 25 Jan 2025 21:58:10 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/transmissao-de-dados-usando-som-via-telefone-de-copos/</guid><description>&lt;p>Quando comecei a brincar com computadores, a única forma de carregar um programa na máquina era digitando-o do zero. Meu computador antigo não tinha armazenamento; não havia HD, disquete ou qualquer outro meio de armazenar dados. Ao iniciar, a máquina carregava o &lt;em>BASIC&lt;/em> diretamente da ROM e pronto. Com o tempo, consegui um gravador de fita, mas ele era terrível. Sem dinheiro para um gravador específico para computadores, usei um gravador doméstico. Demorou bastante ajustando o volume e outros parâmetros até conseguir carregar algo. O equipamento era tão delicado que prendi os controles com fita adesiva para evitar alterações porque qualquer coisa impedia o carregamento.&lt;/p></description></item><item><title>Compilação Estática do Interpretador Lua: Garantia de Consistência e Portabilidade</title><link>https://crg.eti.br/pt-br/pub/compilacao-estatica-da-lingagem-lua/</link><pubDate>Sun, 19 Jan 2025 11:21:08 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/compilacao-estatica-da-lingagem-lua/</guid><description>&lt;p>A linguagem Lua é minha favorita para desenvolver pequenos scripts e configurações. Ela é fácil de incluir em outros projetos e possui uma sintaxe limpa e simples. É fácil de estender e uma ótima linguagem para configurar sistemas.&lt;/p>
&lt;p>Recentemente, iniciei um projeto que requer que o interpretador Lua esteja instalado. Isso normalmente não é um problema. Porém, para garantir total controle, decidi compilar minha própria versão do interpretador de forma estática. Isso assegura que diferenças na versão da libc ou em outras bibliotecas não interfiram no funcionamento do meu sistema. Já enfrentei muitos problemas com sistemas que não carregavam devido a versões diferentes da glibc. Além dos motivos práticos, acredito que todo software deve ser compilado estaticamente. O ganho de memória e a facilidade de atualização da compilação dinâmica não compensam os problemas que podem surgir.&lt;/p></description></item><item><title>Como Encontrar Caminhos de Programas no Sistema com exec.LookPath em Go</title><link>https://crg.eti.br/pt-br/pub/encontrando-os-paths-de-executaveis-usando-go/</link><pubDate>Sat, 18 Jan 2025 22:58:48 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/encontrando-os-paths-de-executaveis-usando-go/</guid><description>&lt;p>Comecei um novo projeto que precisa verificar se alguns programas estão instalados no sistema e obter seus caminhos completos. Para isso, utilizei a função &lt;code>exec.LookPath&lt;/code> do pacote &lt;code>os/exec&lt;/code>.&lt;/p>
&lt;p>A função &lt;code>exec.LookPath&lt;/code> busca um executável nos diretórios listados na variável de ambiente &lt;code>PATH&lt;/code>. Se não encontrar, retorna um erro. Portanto, criei a função &lt;code>programPath&lt;/code> que recebe o nome do programa e retorna o caminho do executável e um booleano indicando se o programa foi encontrado.&lt;/p></description></item><item><title>Otimizando a Verificação de Integridade de Mensagens com FNV-1a em Go</title><link>https://crg.eti.br/pt-br/pub/checksum-com-golang/</link><pubDate>Sat, 18 Jan 2025 00:43:18 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/checksum-com-golang/</guid><description>&lt;p>Vimos no artigo &lt;a href="https://crg.eti.br/pt-br/pub/hmac-assinatura-de-mensagens-segura-em-go/">HMAC (Hash-based Message Authentication Code)&lt;/a> como essa técnica garante que a mensagem não foi alterada durante o transporte e confirma a validade da assinatura.&lt;/p>
&lt;p>No entanto, esse processo, embora seguro, é lento e consome muitos recursos. Quando precisamos apenas verificar a integridade da mensagem sem validar uma assinatura, podemos usar uma função de hash mais rápida. Para isso, utilizaremos o algoritmo FNV-1a (Fowler-Noll-Vo), conhecido por sua rapidez e baixa taxa de colisão.&lt;/p></description></item><item><title>mTLS: Implementando Autenticação Mútua entre Cliente e Servidor em Go</title><link>https://crg.eti.br/pt-br/pub/mtls-implementando-autenticacao-mutua/</link><pubDate>Sat, 11 Jan 2025 19:49:40 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/mtls-implementando-autenticacao-mutua/</guid><description>&lt;p>mTLS (Mutual TLS) autentica mutuamente cliente e servidor. Ambos apresentam certificados digitais assinados por uma autoridade certificadora confiável. Controlando a emissão dos certificados, você garante que apenas clientes autorizados acessem seu serviço. Além disso, identifica facilmente o cliente sem precisar de uma API Key ou Token. Também recomendo usar um cabeçalho &lt;a href="https://crg.eti.br/pt-br/pub/hmac-assinatura-de-mensagens-segura-em-go/">HMAC (Hash-based Message Authentication Code)&lt;/a> como camada adicional de segurança e integridade da mensagem.&lt;/p>
&lt;h2 id="criando-certificados">Criando Certificados&lt;/h2>
&lt;p>Neste exemplo, criarei os certificados de forma simples para testes locais. Ao implementar em produção, tome cuidado com os parâmetros utilizados. É importante incluir Subject Alternative Names (SANs), pois apenas o CN (Common Name) não é mais recomendado.&lt;/p></description></item><item><title>HMAC (Hash-based Message Authentication Code) em Golang</title><link>https://crg.eti.br/pt-br/pub/hmac-assinatura-de-mensagens-segura-em-go/</link><pubDate>Fri, 10 Jan 2025 23:33:11 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/hmac-assinatura-de-mensagens-segura-em-go/</guid><description>&lt;p>Quando criamos APIs, é recomendável adicionar um cabeçalho de autenticação para garantir a integridade das mensagens. Por exemplo, quando seu servidor envia uma requisição ou um webhook, inclua um cabeçalho &lt;code>X-Signature&lt;/code> com uma assinatura HMAC (Hash-based Message Authentication Code).&lt;/p>
&lt;p>Para gerar a assinatura HMAC, você utiliza uma chave secreta e o conteúdo a ser assinado, como o &lt;em>body&lt;/em> da requisição. E envia a assinatura no cabeçalho. É importante deixar claro o que está sendo assinado. Já enfrentei problemas com clientes que não conseguiam validar a assinatura porque usavam o &lt;em>body&lt;/em> parseado como JSON em vez do &lt;em>body raw&lt;/em> recebido na requisição.&lt;/p></description></item><item><title>Validação e Integração Segura de JSON em APIs Go com json.RawMessage</title><link>https://crg.eti.br/pt-br/pub/validacao-e-integracao-segura-de-json-em-apis-go/</link><pubDate>Thu, 09 Jan 2025 00:28:29 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/validacao-e-integracao-segura-de-json-em-apis-go/</guid><description>&lt;p>Recentemente, desenvolvi uma API onde o usuário envia um JSON em um dos campos. O requisito é registrar erros de JSON inválido nos logs, mas permitir que os demais dados continuem o fluxo normal do sistema.&lt;/p>
&lt;p>Também era importante que, se o JSON recebido fosse válido, ele fosse integrado perfeitamente nas respostas da API. Como o JSON poderia variar e eu não conhecia sua estrutura, utilizei &lt;code>json.RawMessage&lt;/code> no tipo do campo. Assim, ao usar a função &lt;code>json.Marshal&lt;/code>, os dados são corretamente incorporados ao JSON principal.&lt;/p></description></item><item><title>Fork bomb: Do Código à Defesa</title><link>https://crg.eti.br/pt-br/pub/forkbomb-do-codigo-a-defesa/</link><pubDate>Sat, 04 Jan 2025 11:48:47 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/forkbomb-do-codigo-a-defesa/</guid><description>&lt;p>A primeira vez que ouvi falar de fork bomb foi há bastante tempo. Embora achasse fascinante um código que gera outros dois processos de si mesmo, causando crescimento exponencial de processos e eventualmente travando o sistema, eu não acreditava que fosse um ataque viável até descobrir quantos sistemas são vulneráveis à injeção de código.&lt;/p>
&lt;h2 id="o-que-é-um-fork-bomb">O que é um fork bomb?&lt;/h2>
&lt;p>Em linhas gerais, um fork bomb é um código que gera processos recursivamente. O primeiro processo gera cópias de si mesmo, e essas cópias geram mais cópias, e assim por diante, até que o sistema fique sem recursos e trave. O resultado é um ataque DoS (Denial of Service).&lt;/p></description></item><item><title>Manipulando bits de permissão especiais</title><link>https://crg.eti.br/pt-br/pub/manipulando-setuid-e-setgid/</link><pubDate>Sat, 04 Jan 2025 00:36:51 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/manipulando-setuid-e-setgid/</guid><description>&lt;p>No artigo sobre &lt;a href="https://crg.eti.br/pt-br/pub/reducao-de-privilegios-com-golang/">Redução de Privilégios em Programas&lt;/a>, utilizamos o comando &lt;code>sudo&lt;/code> para executar um programa com privilégios de superusuário. No entanto, é possível realizar essa ação sem usar um comando externo.&lt;/p>
&lt;p>Para isso, usamos permissões especiais de arquivos conhecidas como &lt;em>bit setuid&lt;/em> e &lt;em>bit setgid&lt;/em>. Esses atributos permitem que arquivos sejam executados com os &lt;strong>privilégios do usuário ou do grupo proprietário&lt;/strong>.&lt;/p>
&lt;p>Para ajustar os bits &lt;code>setuid&lt;/code> e &lt;code>setgid&lt;/code>, utilizamos o comando &lt;code>chmod&lt;/code> com as opções &lt;code>u+s&lt;/code> e &lt;code>g+s&lt;/code>, respectivamente.&lt;/p></description></item><item><title>Redução de Privilégios em Programas Go para Aumentar a Segurança</title><link>https://crg.eti.br/pt-br/pub/reducao-de-privilegios-com-golang/</link><pubDate>Thu, 02 Jan 2025 22:43:45 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/reducao-de-privilegios-com-golang/</guid><description>&lt;p>Uma boa prática para aumentar a segurança de um sistema é reduzir os privilégios de execução de um programa. Idealmente, um programa deve rodar com o mínimo de privilégios possíveis.&lt;/p>
&lt;p>Em sistemas UNIX-like, é possível alterar o usuário e o grupo em que um programa é executado. Vamos ver um passo a passo de como fazer isso em Golang.&lt;/p>
&lt;h2 id="verificando-se-o-programa-está-rodando-como-root">Verificando se o Programa está Rodando como Root&lt;/h2>
&lt;p>Primeiro, verifique se o programa está sendo executado como root. Isso é importante porque usaremos chamadas de sistema que necessitam de privilégios de root. (Existem outras maneiras de conceder esses privilégios, mas abordaremos isso em outro artigo.)&lt;/p></description></item><item><title>Referências nos comentários com Golang</title><link>https://crg.eti.br/pt-br/pub/referencias-nos-comentarios-com-golang/</link><pubDate>Wed, 01 Jan 2025 13:28:17 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/referencias-nos-comentarios-com-golang/</guid><description>&lt;p>Uma dica rápida sobre comentários em Go é incluir referências neles. Coloque o elemento que deseja referenciar entre colchetes (&lt;strong>[&lt;/strong> e &lt;strong>]&lt;/strong>), funciona com tudo que pode ser referenciado, como variáveis, constantes, funções, etc.&lt;/p>
&lt;p>Veja o 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-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">package&lt;/span> &lt;span style="color:#1f2328">main&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">import&lt;/span> &lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#34;time&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>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">// pi representa a constante matemática Pi&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">pi&lt;/span> &lt;span style="color:#1f2328">=&lt;/span> &lt;span style="color:#0550ae">3.14159&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">// CalcularArea calcula a área de um círculo dado o raio.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">// Utiliza a constante [pi] para o cálculo.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">func&lt;/span> &lt;span style="color:#6639ba">CalcularArea&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">raio&lt;/span> &lt;span style="color:#cf222e">float64&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#cf222e">float64&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">pi&lt;/span> &lt;span style="color:#0550ae">*&lt;/span> &lt;span style="color:#1f2328">raio&lt;/span> &lt;span style="color:#0550ae">*&lt;/span> &lt;span style="color:#1f2328">raio&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:#cf222e">func&lt;/span> &lt;span style="color:#6639ba">main&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">raio&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#0550ae">5.0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">area&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#6639ba">CalcularArea&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">raio&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">fmt&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Printf&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#34;A área do círculo com raio %.2f é %.2f\n&amp;#34;&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">raio&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">area&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>&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 style="color:#57606a"> Formatos úteis:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"> [time.DateTime]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"> [time.Kitchen]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"> [time.RFC3339Nano]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a"> [time.RFC3339]
&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 style="color:#1f2328">fmt&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Println&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">time&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Now&lt;/span>&lt;span style="color:#1f2328">().&lt;/span>&lt;span style="color:#6639ba">Format&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">time&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">DateTime&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>No Neovim, coloque o cursor entre os colchetes e pressione &lt;code>Ctrl-]&lt;/code> para ir até a definição do elemento referenciado. Para voltar, pressione &lt;code>Ctrl-t&lt;/code>. No VSCode, use a extensão &lt;code>Go to Definition&lt;/code> para realizar a mesma ação.&lt;/p></description></item><item><title>Efeito plasma no terminal com Golang</title><link>https://crg.eti.br/pt-br/pub/efeito-plasma-no-terminal-com-golang/</link><pubDate>Tue, 31 Dec 2024 17:34:13 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/efeito-plasma-no-terminal-com-golang/</guid><description>&lt;p>Um dos programas que sempre achei interessantes são as &lt;em>demos&lt;/em> com efeitos gráficos atrativos e códigos que extraem cada grama de performance da máquina. O efeito plasma é um dos que considero mais legais, simulando um fluido em movimento.&lt;/p>
&lt;figure class="media-frame media-center fade-in">&lt;a href="https://crg.eti.br/pub/efeito-plasma-no-terminal-com-golang/plasma.webp">
&lt;picture>
&lt;source media="(max-width: 480px)" srcset="https://crg.eti.br/pub/efeito-plasma-no-terminal-com-golang/plasma_hu_3e89f9757017ba57.webp">
&lt;source media="(max-width: 1080px)" srcset="https://crg.eti.br/pub/efeito-plasma-no-terminal-com-golang/plasma_hu_3490c725fbb4fdb0.webp">
&lt;img alt="plasma no terminal com Go" src="https://crg.eti.br/pub/efeito-plasma-no-terminal-com-golang/plasma_hu_5639f6b4b1ba2b78.webp" height="832" width="1280" loading="lazy" decoding="async">
&lt;/picture>
&lt;/a>&lt;/figure>&lt;p>Para criar o efeito plasma, utilizo várias funções trigonométricas para calcular a cor de fundo de cada caractere e passo o tempo para gerar a animação. O código é relativamente simples, mas a otimização é um pouco mais complexa.&lt;/p></description></item><item><title>Feliz 2025, fogos de artifício no terminal com Golang</title><link>https://crg.eti.br/pt-br/pub/feliz-2025-com-fogos-de-artificio-no-terminal-com-golang/</link><pubDate>Tue, 31 Dec 2024 13:09:42 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/feliz-2025-com-fogos-de-artificio-no-terminal-com-golang/</guid><description>&lt;p>Um pequeno programa comemora a chegada de 2025 com fogos de artifício no terminal. Com vários truques interessantes para você iniciar o ano com muito código.&lt;/p>
&lt;figure class="media-frame media-center fade-in">&lt;a href="https://crg.eti.br/pub/feliz-2025-com-fogos-de-artificio-no-terminal-com-golang/fireworks-em-golang.webp">
&lt;picture>
&lt;source media="(max-width: 480px)" srcset="https://crg.eti.br/pub/feliz-2025-com-fogos-de-artificio-no-terminal-com-golang/fireworks-em-golang_hu_540d81dfb0c7b7ac.webp">
&lt;source media="(max-width: 1080px)" srcset="https://crg.eti.br/pub/feliz-2025-com-fogos-de-artificio-no-terminal-com-golang/fireworks-em-golang_hu_a9d6cf735954d9aa.webp">
&lt;img alt="fireworks em Go" src="https://crg.eti.br/pub/feliz-2025-com-fogos-de-artificio-no-terminal-com-golang/fireworks-em-golang_hu_87a35e7dddfadd11.webp" height="1532" width="2188" loading="lazy" decoding="async">
&lt;/picture>
&lt;/a>&lt;/figure>&lt;p>Usamos &lt;code>os.Stdout.WriteString&lt;/code> para escrever diretamente no descritor do stdout, ou seja, na saída padrão do terminal. Essa é a forma mais rápida de escrever no terminal, mas não é sincronizada. Isso significa que não há garantia de que a saída será escrita na ordem esperada. Mas no nosso caso isso é desejável porque permite que os fogos de artifício se sobreponham, dando a impressão de que estão explodindo simultaneamente.&lt;/p></description></item><item><title>Reescrevendo o velho TSR usando Bash</title><link>https://crg.eti.br/pt-br/pub/reescrevendo-velho-tsr-usando-bash/</link><pubDate>Sat, 21 Dec 2024 17:26:25 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/reescrevendo-velho-tsr-usando-bash/</guid><description>&lt;p>Quando comecei a programar, a computação era diferente de hoje. O sistema operacional era mono-tarefa; apenas um programa podia ser executado por vez. Não havia recursos modernos, como memória protegida e mapeada. Mesmo assim, era possível criar comportamentos concorrentes nos programas, mas era preciso cuidado para evitar que alguma parte bloqueasse o processamento. Por exemplo, não podia haver loops esperando entrada do teclado ou processos muito longos. Criar um programa sem bloqueios era complicado em linguagens como Clipper.&lt;/p></description></item><item><title>Subindo uma API via proxy reverso com Caddyserver e Go</title><link>https://crg.eti.br/pt-br/pub/subindo-api-via-proxy-reverso-caddy-go/</link><pubDate>Fri, 20 Dec 2024 01:34:17 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/subindo-api-via-proxy-reverso-caddy-go/</guid><description>&lt;p>Um amigo pediu um exemplo de como subir uma API usando proxy reverso com a linguagem Go. A seguir, apresento um pequeno roteiro.&lt;/p>
&lt;p>Primeiro, suba um servidor e registre seu IP no provedor de DNS. Atribua o IP a um nome para criar um certificado HTTPS para a máquina.&lt;/p>
&lt;p>Configure o firewall da máquina e abra apenas as portas 22 (SSH), 80 (HTTP) e 443 (HTTPS).&lt;/p>
&lt;h2 id="caddy">Caddy&lt;/h2>
&lt;p>Eu uso o servidor HTTP Caddy. Ele é prático e cria certificados HTTPS automaticamente. Por padrão, redireciona as requisições HTTP para HTTPS.&lt;/p></description></item><item><title>Benchmark Retornos Nomeados vs Explicitos em Go</title><link>https://crg.eti.br/pt-br/pub/benchmark-retornos-nomeados-vs-explicitos-go/</link><pubDate>Tue, 17 Dec 2024 03:00:24 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/benchmark-retornos-nomeados-vs-explicitos-go/</guid><description>&lt;p>No nosso grupo de estudos de Go, surgiu uma dúvida: retornos nomeados são mais rápidos que retornos explícitos? A hipótese é essa.&lt;/p>
&lt;p>Felizmente, Go tem boas ferramentas para testar isso.&lt;/p>
&lt;p>Vamos criar um código com duas funções de soma: uma com retornos nomeados e outra com retornos explícitos.&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">package&lt;/span> &lt;span style="color:#1f2328">main&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">import&lt;/span> &lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#34;testing&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>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#57606a">// Função com retornos nomeados&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">func&lt;/span> &lt;span style="color:#6639ba">somaNomeados&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">a&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">b&lt;/span> &lt;span style="color:#cf222e">int&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">resultado&lt;/span> &lt;span style="color:#cf222e">int&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">err&lt;/span> &lt;span style="color:#cf222e">error&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">resultado&lt;/span> &lt;span style="color:#1f2328">=&lt;/span> &lt;span style="color:#1f2328">a&lt;/span> &lt;span style="color:#0550ae">+&lt;/span> &lt;span style="color:#1f2328">b&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:#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">// Função com retornos explícitos&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">func&lt;/span> &lt;span style="color:#6639ba">somaExplicitos&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">a&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">b&lt;/span> &lt;span style="color:#cf222e">int&lt;/span>&lt;span style="color:#1f2328">)&lt;/span> &lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#cf222e">int&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#cf222e">error&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:#1f2328">a&lt;/span> &lt;span style="color:#0550ae">+&lt;/span> &lt;span style="color:#1f2328">b&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#cf222e">nil&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>Depois, criamos as funções de benchmark. O nome dessas funções é importante. A ferramenta de testes do Go procura funções que começam com &amp;ldquo;Benchmark&amp;rdquo;.&lt;/p></description></item><item><title>Escrevendo Sobre Programação de Computadores</title><link>https://crg.eti.br/pt-br/pub/escrevendo-sobre-programacao-de-computadores/</link><pubDate>Sun, 15 Dec 2024 17:29:11 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/escrevendo-sobre-programacao-de-computadores/</guid><description>&lt;p>Escrever sobre programação e informática é desafiador. Esses temas são complexos e é difícil criar uma narrativa compreensível e interessante.&lt;/p>
&lt;p>Além disso, o português é um idioma exigente. Tenho a tendência de escrever como falo, o que resulta em textos difíceis de ler.&lt;/p>
&lt;p>Para facilitar, criei algumas regras que servem como guia. Elas não são rígidas, apenas orientações sem uma ordem específica.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Seja direto ao ponto.&lt;/strong> Evite floreios desnecessários e vá direto ao assunto.&lt;/p></description></item><item><title>Personalizando o Neovim: Ordenação e Remoção de Linhas Duplicadas com Lua</title><link>https://crg.eti.br/pt-br/pub/personalizando_neovim_ordenacao_e_remocao_de_linhas_duplicadas_com_lua/</link><pubDate>Fri, 29 Nov 2024 00:31:30 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/personalizando_neovim_ordenacao_e_remocao_de_linhas_duplicadas_com_lua/</guid><description>&lt;p>Continuando as personalizações do Neovim, apresento duas funções que uso frequentemente: &lt;code>sort_lines&lt;/code> e &lt;code>sort_and_uniq_lines&lt;/code>. Como o nome sugere, elas ordenam o conteúdo das linhas selecionadas e, no caso de &lt;code>sort_and_uniq_lines&lt;/code>, também eliminam duplicatas.&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:#cf222e">function&lt;/span> &lt;span style="color:#6639ba">sort_lines&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">-- Obter a posição inicial e final da seleção&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> start_pos &lt;span style="color:#0550ae">=&lt;/span> vim.fn&lt;span style="color:#1f2328">.&lt;/span>getpos&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&amp;#39;&amp;lt;&amp;#34;&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> end_pos &lt;span style="color:#0550ae">=&lt;/span> vim.fn&lt;span style="color:#1f2328">.&lt;/span>getpos&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&amp;#39;&amp;gt;&amp;#34;&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">-- Converter a posição para o índice da linha&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">-- Ajuste start_pos porque as linhas no Lua começam do 0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> start_line &lt;span style="color:#0550ae">=&lt;/span> start_pos&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#0550ae">2&lt;/span>&lt;span style="color:#1f2328">]&lt;/span> &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:#57606a">-- Não precisa ajustar end_line&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> end_line &lt;span style="color:#0550ae">=&lt;/span> end_pos&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#0550ae">2&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">-- Obter as linhas selecionadas&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> lines &lt;span style="color:#0550ae">=&lt;/span> vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_buf_get_lines&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">0&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> start_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> end_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&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">-- Ordenar as linhas&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> table.sort&lt;span style="color:#1f2328">(&lt;/span>lines&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">-- Substituir as linhas originais&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_buf_set_lines&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">0&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> start_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> end_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">false&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> lines
&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">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:#cf222e">function&lt;/span> &lt;span style="color:#6639ba">sort_and_uniq_lines&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> start_pos &lt;span style="color:#0550ae">=&lt;/span> vim.fn&lt;span style="color:#1f2328">.&lt;/span>getpos&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&amp;#39;&amp;lt;&amp;#34;&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> end_pos &lt;span style="color:#0550ae">=&lt;/span> vim.fn&lt;span style="color:#1f2328">.&lt;/span>getpos&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;&amp;#39;&amp;gt;&amp;#34;&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">local&lt;/span> start_line &lt;span style="color:#0550ae">=&lt;/span> start_pos&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#0550ae">2&lt;/span>&lt;span style="color:#1f2328">]&lt;/span> &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">local&lt;/span> end_line &lt;span style="color:#0550ae">=&lt;/span> end_pos&lt;span style="color:#1f2328">[&lt;/span>&lt;span style="color:#0550ae">2&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">local&lt;/span> lines &lt;span style="color:#0550ae">=&lt;/span> vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_buf_get_lines&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">0&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> start_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> end_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&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> table.sort&lt;span style="color:#1f2328">(&lt;/span>lines&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">-- Remover linhas duplicadas&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">local&lt;/span> uniq_lines &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">local&lt;/span> last_line &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#cf222e">nil&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> line &lt;span style="color:#cf222e">in&lt;/span> ipairs&lt;span style="color:#1f2328">(&lt;/span>lines&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">if&lt;/span> line &lt;span style="color:#0550ae">~=&lt;/span> last_line &lt;span style="color:#cf222e">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> table.insert&lt;span style="color:#1f2328">(&lt;/span>uniq_lines&lt;span style="color:#1f2328">,&lt;/span> line&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> last_line &lt;span style="color:#0550ae">=&lt;/span> line
&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> vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_buf_set_lines&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0550ae">0&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> start_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> end_line&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">false&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> uniq_lines
&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">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>vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_set_keymap&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#39;v&amp;#39;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#39;&amp;lt;Leader&amp;gt;s&amp;#39;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#39;:lua sort_lines()&amp;lt;CR&amp;gt;&amp;#39;&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> noremap &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#cf222e">true&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> silent &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#cf222e">true&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>vim.api&lt;span style="color:#1f2328">.&lt;/span>nvim_set_keymap&lt;span style="color:#1f2328">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#39;v&amp;#39;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#39;&amp;lt;Leader&amp;gt;u&amp;#39;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#0a3069">&amp;#39;:lua sort_and_uniq_lines()&amp;lt;CR&amp;gt;&amp;#39;&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> noremap &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#cf222e">true&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> silent &lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#cf222e">true&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>&lt;a href="https://crg.eti.br/pub/personalizando_neovim_ordenacao_e_remocao_de_linhas_duplicadas_com_lua/sort_lines.lua">sort_lines.lua&lt;/a>&lt;/p></description></item><item><title>Criando um Sistema de Bookmarks no Neovim com Lua</title><link>https://crg.eti.br/pt-br/pub/criando-sistema-de-bookmarks-no-neovim-com-lua/</link><pubDate>Mon, 25 Nov 2024 00:25:27 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/criando-sistema-de-bookmarks-no-neovim-com-lua/</guid><description>&lt;p>Continuando nossa série de artigos que visam diminuir o esforço cognitivo em tarefas de programação, apresento meu pequeno script de bookmarks para o Neovim.&lt;/p>
&lt;p>O Neovim é incrivelmente personalizável. Sem a necessidade de criar plugins completos, você pode, com algumas funções Lua, adicionar muitas funcionalidades.&lt;/p>
&lt;p>No meu dia a dia, frequentemente preciso retornar aos mesmos arquivos para corrigir e testar problemas. Abrir esses arquivos diretamente na linha correta, sem perder tempo navegando, é essencial.&lt;/p></description></item><item><title>Script para rápida navegação em diretórios usando fzf</title><link>https://crg.eti.br/pt-br/pub/script-rapido-navegacao-diretorios-fzf/</link><pubDate>Sun, 24 Nov 2024 15:43:50 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/script-rapido-navegacao-diretorios-fzf/</guid><description>&lt;p>Este artigo apresenta um script para tornar a navegação em diretórios mais rápida, continuando a série sobre redução da complexidade cognitiva.&lt;/p>
&lt;p>Frequentemente, é necessário navegar entre vários diretórios de um ou múltiplos projetos. Lembrar os caminhos e localizar arquivos torna-se um esforço desnecessário.&lt;/p>
&lt;p>Uma solução é manter uma lista dos últimos diretórios acessados para alternar rapidamente entre eles. Dave Eddy implementou essa ideia em seu &lt;a href="https://github.com/bahamas10/bash-cdstack">cdstack&lt;/a>.&lt;/p>
&lt;p>Inspirado nessa abordagem, criei minha versão mais adequada ao meu modo de trabalho.&lt;/p></description></item><item><title>Diminuindo a Complexidade Cognitiva na Programação</title><link>https://crg.eti.br/pt-br/pub/diminuindo-a-complexidade-cognitiva-na-programacao/</link><pubDate>Sat, 23 Nov 2024 21:28:27 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/diminuindo-a-complexidade-cognitiva-na-programacao/</guid><description>&lt;p>Eu dedico muito tempo e esforço para diminuir a complexidade cognitiva ao programar.&lt;/p>
&lt;p>Complexidade cognitiva é o quanto se precisa pensar para realizar uma tarefa. Pequenos detalhes podem tornar uma tarefa desnecessariamente complexa.&lt;/p>
&lt;p>Por exemplo, encontrar um trecho de código escondido em muitos arquivos dentro de uma grande estrutura de diretórios exige esforço. Mesmo que a estrutura seja familiar e bem projetada, o objetivo não é navegar por ela abrindo arquivos até encontrar o código para editar; o objetivo é apenas editar o código. Qualquer coisa além disso é esforço cognitivo desperdiçado.&lt;/p></description></item><item><title>Reestruturando artigos para clareza e concisão</title><link>https://crg.eti.br/pt-br/pub/reestruturando-artigos-para-clareza-e-concisao/</link><pubDate>Sat, 23 Nov 2024 19:53:57 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/reestruturando-artigos-para-clareza-e-concisao/</guid><description>&lt;p>Estou reestruturando a forma dos artigos neste site.&lt;/p>
&lt;p>Geralmente escrevo como falo, o que algumas pessoas acham agradável. No entanto, minha relação de amor e ódio com a língua portuguesa às vezes torna meus textos difíceis de entender. Também costumo me alongar demais ao explicar motivos e conceitos, deixando o texto maçante.&lt;/p>
&lt;p>Como exercício de escrita, estou revisando meus textos. Corrigindo problemas de ortografia e gramática e tornando o conteúdo mais direto.&lt;/p></description></item><item><title>Virus no laboratório</title><link>https://crg.eti.br/pt-br/pub/virus-no-laboratorio/</link><pubDate>Fri, 25 Oct 2024 22:43:08 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/virus-no-laboratorio/</guid><description>&lt;p>Essa história é lá da primeira metade dos anos 2000, na época eu trabalhava em uma empresa que criava hardware para telefonia.&lt;/p>
&lt;p>Era bem interessante, tive acesso a algumas maquinas NEC legais e escrevi alguns códigos bem interessantes.&lt;/p>
&lt;p>Foi nessa época que eu escrevi um gravador para VoIP capturando diretamente os pacotes SIP da rede, menos de 100 linhas de código C, mas isso é história para outro dia.&lt;/p>
&lt;p>Um dia um cliente ligou reclamando que o sistema dele estava muito lento, era um cliente grande, um laboratório farmacêutico aqui de São Paulo.&lt;/p></description></item><item><title>Programação como Arte</title><link>https://crg.eti.br/pt-br/pub/arte-generativa-em-javascript-segunda-parte/</link><pubDate>Sun, 29 Sep 2024 16:24:25 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/arte-generativa-em-javascript-segunda-parte/</guid><description>&lt;p>Considero programar computadores uma forma de expressão artística. Existem muitas maneiras de resolver problemas do dia a dia da programação, deixando muito espaço para criatividade.&lt;/p>
&lt;p>&lt;canvas id="grid_rect_canvas" class="genart_full">&lt;/canvas>&lt;/p>
&lt;h2 id="exemplos-clássicos-de-arte-generativa">Exemplos Clássicos de Arte Generativa&lt;/h2>
&lt;p>E existem muitos exemplos interessantes de arte gerada por computador. Os meus favoritos são os &amp;ldquo;one-liners&amp;rdquo;, programas de apenas uma linha que fazem coisas interessantes, como o famoso &lt;code>10 PRINT CHR$ (205.5 + RND (1)); : GOTO 10&lt;/code> que desenha um labirinto usando &lt;em>BASIC&lt;/em>, e o equivalente mais moderno yes &lt;code>yes 'c=(╱ ╲);printf ${c[RANDOM%2]}'|bash&lt;/code> criado usando &lt;em>Bash&lt;/em>. Uma rápida procura na internet vai trazer várias implementações em linguagens diferentes.&lt;/p></description></item><item><title>Arte generativa em JavaScript para as laterais do site</title><link>https://crg.eti.br/pt-br/pub/arte-generativa-em-javascript/</link><pubDate>Sun, 25 Aug 2024 18:35:45 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/arte-generativa-em-javascript/</guid><description>&lt;p>Após bastante tempo, finalmente inclui um JavaScript neste site.&lt;/p>
&lt;p>Eu tenho um bloqueio enorme com relação ao uso de tecnologias para web, JavaScript, CSS e o próprio HTML parecem muito improvisadas para mim, principalmente a ideia de &amp;ldquo;single page application&amp;rdquo;.&lt;/p>
&lt;p>Essa é uma limitação que eu tenho que superar. Mesmo porque, hoje em dia, a web é de fato a melhor e mais portável interface para a maioria dos programas. Apesar de ir contra muita coisa que acredito sobre minimalismo e economia de recursos.&lt;/p></description></item><item><title>Computação pós-apocalíptica</title><link>https://crg.eti.br/pt-br/pub/computacao-pos-apocaliptica/</link><pubDate>Sat, 13 Jul 2024 18:17:36 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/computacao-pos-apocaliptica/</guid><description>&lt;p>Computação pós-apocalíptica é uma brincadeira, um exercício interessante para sua imaginação. O cenário é o seguinte, aconteceu algo terrível e a sociedade em que você vive não existe mais. Como sobrevivente, cabe a você ajudar a reconstruir a sociedade moderna.&lt;/p>
&lt;figure class="media-frame media-center fade-in">&lt;a href="https://crg.eti.br/pub/computacao-pos-apocaliptica/computacao-pos-apocaliptica-0.webp">
&lt;picture>
&lt;source media="(max-width: 480px)" srcset="https://crg.eti.br/pub/computacao-pos-apocaliptica/computacao-pos-apocaliptica-0_hu_c3f0f04a4b3b30ce.webp">
&lt;source media="(max-width: 1080px)" srcset="https://crg.eti.br/pub/computacao-pos-apocaliptica/computacao-pos-apocaliptica-0_hu_c263a07ecdd35615.webp">
&lt;img alt="Computação pós-apocalíptica" src="https://crg.eti.br/pub/computacao-pos-apocaliptica/computacao-pos-apocaliptica-0_hu_371655508fb5b573.webp" height="200" width="200" loading="lazy" decoding="async">
&lt;/picture>
&lt;/a>&lt;/figure>&lt;p>O motivo do apocalipse pode ser o que você preferir, guerra nuclear, praga, colapso econômico, tempestade solar, governo opressor que quer manter a tecnologia apenas para si, etc., a única constante é que nada que você tem como garantido está disponível. Toda a infraestrutura se foi, não temos mais água encanada, eletricidade, nem nenhuma das amenidades da vida moderna.&lt;/p></description></item><item><title>Criando o próprio sistema para contar o tempo</title><link>https://crg.eti.br/pt-br/pub/internet-time/</link><pubDate>Thu, 16 May 2024 11:39:44 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/internet-time/</guid><description>&lt;p>Medir o tempo é uma tarefa séria e mais complicada do que parece. Como bom nerd, sou fascinado pelos vários métodos de medir e contar o tempo. Um dos que mais me chama a atenção é o &amp;ldquo;&lt;a href="https://en.wikipedia.org/wiki/Decimal_time">tempo decimal&lt;/a>&amp;rdquo;.&lt;/p>
&lt;p>Existem várias implementações de tempo decimal, dividindo geralmente o dia em 10 horas de 100 minutos cada. Outra abordagem é ignorar as horas e usar apenas os minutos como um número contínuo. Se precisar de mais precisão, basta usar frações desse minuto, quantas casas decimais forem necessárias.&lt;/p></description></item><item><title>Deploy de aplicação usando curl</title><link>https://crg.eti.br/pt-br/pub/deploy_de_aplicacoes_usando_curl/</link><pubDate>Sat, 09 Mar 2024 11:45:51 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/deploy_de_aplicacoes_usando_curl/</guid><description>&lt;p>Existem vários desafios para pequenas equipes distribuírem binários atualmente. Se você simplesmente colocar um aplicativo para download em um site, imediatamente as ferramentas de busca vão marcar seu site como conteúdo suspeito. Os navegadores colocam um aviso assustador para o usuário e não existe como remover esse aviso, mesmo com o binário assinado. O aviso só é removido se houver usuários suficientes fazendo download do seu binário sem reportar problemas.&lt;/p></description></item><item><title>ps - hierarquia de processos</title><link>https://crg.eti.br/pt-br/pub/hierarquia-de-processos/</link><pubDate>Sun, 11 Feb 2024 14:13:47 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/hierarquia-de-processos/</guid><description>&lt;p>Quando comecei a usar o &lt;a href="https://github.com/crgimenes/compterm">compterm&lt;/a> um problema logo apareceu, às vezes eu esquecia que o compterm estava carregado. Daí a criei uma pequena função para detectar se eu estava em uma sessão carregada pelo compterm ou se era apenas uma sessão normal do zsh.&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:#cf222e">function&lt;/span> is_parent_compterm &lt;span style="color:#0550ae">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6639ba">local&lt;/span> &lt;span style="color:#953800">pid&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#953800">$$&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#6639ba">local&lt;/span> parent_pid
&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">while&lt;/span> &lt;span style="color:#0550ae">[&lt;/span> &lt;span style="color:#0a3069">&amp;#34;&lt;/span>&lt;span style="color:#953800">$pid&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:#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:#953800">parent_pid&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#cf222e">$(&lt;/span>ps -p &lt;span style="color:#953800">$pid&lt;/span> -o &lt;span style="color:#953800">ppid&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#cf222e">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#953800">parent_pid&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#0a3069">${&lt;/span>&lt;span style="color:#953800">parent_pid&lt;/span>&lt;span style="color:#1f2328">//[[:&lt;/span>&lt;span style="color:#953800">blank&lt;/span>&lt;span style="color:#1f2328">:]]/&lt;/span>&lt;span style="color:#0a3069">}&lt;/span> &lt;span style="color:#57606a"># Remove espaços&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"># Verifica se o nome do comando do processo pai é &amp;#39;compterm&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">if&lt;/span> ps -p &lt;span style="color:#953800">$parent_pid&lt;/span> -o &lt;span style="color:#953800">comm&lt;/span>&lt;span style="color:#0550ae">=&lt;/span> &lt;span style="color:#1f2328">|&lt;/span> grep -q &lt;span style="color:#0a3069">&amp;#34;^compterm&lt;/span>$&lt;span style="color:#0a3069">&amp;#34;&lt;/span>&lt;span style="color:#1f2328">;&lt;/span> &lt;span style="color:#cf222e">then&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:#0550ae">0&lt;/span> &lt;span style="color:#57606a"># Retorna true se encontrar &amp;#39;compterm&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">fi&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:#953800">pid&lt;/span>&lt;span style="color:#0550ae">=&lt;/span>&lt;span style="color:#953800">$parent_pid&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cf222e">done&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">return&lt;/span> &lt;span style="color:#0550ae">1&lt;/span> &lt;span style="color:#57606a"># Retorna false se &amp;#39;compterm&amp;#39; não for encontrado&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;p>Essa função verifica todos os processos parents do processo atual e se o nome de algum deles for compterm retorna true. Com isso consigo personalizar o prompt e assim sei se o compterm está carregado ou não.&lt;/p></description></item><item><title>Estudando Assembly</title><link>https://crg.eti.br/pt-br/pub/estudando-assembly/</link><pubDate>Sat, 22 Jul 2023 10:47:36 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/estudando-assembly/</guid><description>&lt;p>Quando eu comecei a programar, na era do 8bits, aprender um pouco de assembly era inevitável, as maquinas eram muito mais simples que os computadores atuais e geralmente nem mesmo tínhamos um compilador a mão, no lugar digitávamos pequenos trechos de opcodes diretamente em hexadecimal.&lt;/p>
&lt;p>Isso era incrivelmente útil para contornar limitações do BASIC que servia tanto como linguagem de programação como sistema operacional. (diretamente gravado na ROM da máquina)&lt;/p></description></item><item><title>Arquivos ocultos no UNIX</title><link>https://crg.eti.br/pt-br/pub/arquivos-ocultos-no-unix/</link><pubDate>Mon, 15 May 2023 06:21:48 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/arquivos-ocultos-no-unix/</guid><description>&lt;p>Todos sabem como criar arquivos ocultos no mundo UNIX/Linux, basta que o nome do arquivo inicie com um ponto (.), mas esse recurso nem sempre existiu.&lt;/p>
&lt;p>De acordo com Rob Pike em um post no Google+ que agora só está disponível em archive.org, lá pela versão 2 do UNIX, enquanto o design do sistema de arquivos Unix estava sendo trabalhado, surgiram as entradas &amp;ldquo;.&amp;rdquo; e &amp;ldquo;..&amp;rdquo; para facilitar a navegação em diretórios. Provavelmente isso aconteceu na versão 2 quando o sistema de arquivos se tornou hierárquico.&lt;/p></description></item><item><title>Por que meu site é tão feio?</title><link>https://crg.eti.br/pt-br/pub/por-que-meu-site-eh-tao-feio/</link><pubDate>Sun, 23 Apr 2023 10:29:39 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/por-que-meu-site-eh-tao-feio/</guid><description>&lt;h2 id="atualização">Atualização&lt;/h2>
&lt;p>Recentemente fui convencido a experimentar um tema mais atual, então estou experimentando um novo tema, mas mantendo a mesma filosofia de acessibilidade e simplicidade. E para variar um tema claro. Além disso, adicionei algum JavaScript, por mais incrível que seja.&lt;/p>
&lt;hr>
&lt;p>Tem sempre alguém perguntando o motivo do meu site ser tão feio, isso já rendeu boas risadas e geralmente serve de gancho para boas conversas. Mas, como já fui perguntado sobre isso várias vezes, é bom deixar uma resposta registrada para quem não tem tanta intimidade (ou falta de vergonha) para me perguntar isso.&lt;/p></description></item><item><title>Programação assistida por IA</title><link>https://crg.eti.br/pt-br/pub/programacao-assistida-por-ia/</link><pubDate>Sat, 22 Apr 2023 09:33:12 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/programacao-assistida-por-ia/</guid><description>&lt;p>Recentemente tivemos uma explosão no uso de inteligência artificial (IA) com produtos como o ChatGPT, Github Copilot, Tabnine, e tantos outros. São ferramentas muito úteis e interessantes, mas não é tanto quanto a mídia diz.&lt;/p>
&lt;p>Pense nessas ferramentas como uma maquina que prevê qual a próxima palavra é a mais adequada e a coloca na sugestão e faz isso repetidamente em loop até atingir um número de palavras ou até a probabilidade de acerto cair abaixo de um valor aceitável, o que vier primeiro.&lt;/p></description></item><item><title>Escrevendo software para durar</title><link>https://crg.eti.br/pt-br/pub/escrevendo-software-para-durar/</link><pubDate>Fri, 21 Apr 2023 16:28:48 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/escrevendo-software-para-durar/</guid><description>&lt;p>Aqui apresentarei alguns tópicos que acredito serem importantes na hora de desenvolver um software de forma que ele seja bastante resiliente e que dure por vários anos. Os tópicos não estão em uma ordem particular e são a minha opinião embasada pela minha experiência como desenvolvedor.&lt;/p>
&lt;p>Encare esse texto como um conjunto de ideias que coletei pelos anos, eu tentei deixar elas o mais genéricas possível, mas não tenho a pretensão de que elas se apliquem a qualquer cenário. Acredito que elas se encaixam melhor se sua equipe é pequena e você precisa entregar rápido.&lt;/p></description></item><item><title>Go e a promessa de retrocompatibilidade</title><link>https://crg.eti.br/pt-br/pub/golang-retrocompatibilidade/</link><pubDate>Wed, 12 Apr 2023 09:24:13 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-retrocompatibilidade/</guid><description>&lt;p>Quando a versão 1.0 da linguagem Go foi lançada, os desenvolvedores assumiram um &lt;a href="https://go.dev/doc/go1compat">compromisso de manter retrocompatibilidade&lt;/a> conforme novas versões fossem surgindo.&lt;/p>
&lt;p>Esse compromisso traz vários resultados interessantes, por exemplo, o código que você aprender não fica desatualizado, além disso, manter a retrocompatibilidade da linguagem reforça outro compromisso importante, o que se refere a simplicidade e legibilidade do código. Aquele projeto que ficou esperando por meses, talvez anos continua compilando de primeira, eu experimentei isso pessoalmente com código que &lt;em>ficou na gaveta&lt;/em> por três anos. &lt;/p></description></item><item><title>Go e erros de arredondamento</title><link>https://crg.eti.br/pt-br/pub/golang-erro-de-arredondamento/</link><pubDate>Wed, 12 Apr 2023 09:24:13 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-erro-de-arredondamento/</guid><description>&lt;p>Quando criamos programas que vão lidar com dinheiro o ideal é sempre usar centavos, assim podemos ter variáveis do tipo inteiro e é bem mais simples prevenir erros causados pela forma &lt;a href="https://en.wikipedia.org/wiki/IEEE_754">como computadores armazenam números de ponto flutuante&lt;/a>.&lt;/p>
&lt;p>Mas nem sempre podemos escolher, quando consumimos &lt;em>APIs&lt;/em> de terceiros, por exemplo, nem sempre as melhores praticas são observadas. Aliás, no dia a dia trabalhando condições ideais são uma raridade.&lt;/p>
&lt;p>A pouco tempo passei por um problema como esse, uma &lt;em>API&lt;/em> que meu sistema precisava consumir retornava um &lt;em>JSON&lt;/em> e o campo com o valor além de ser string era também ponto flutuante.&lt;/p></description></item><item><title>CPBR14, Wardriving</title><link>https://crg.eti.br/pt-br/pub/cpbr14/</link><pubDate>Tue, 08 Nov 2022 08:55:30 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/cpbr14/</guid><description>&lt;p>Links úteis para o workshop &amp;ldquo;Wardriving - Breve introdução, equipamentos e softwares&amp;rdquo; para a Campus Party Brasil 2022.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://wigle.net/">WiGLE Wifi Wardriving&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://apps.apple.com/br/app/gps-2-ip/id408625926">GPS2IP&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/tiagoshibata/Android-GPSd-Forwarder">Android GPSd Forwarder&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.kismetwireless.net/">Kismet Wireless&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://discord.gg/cyberdeck-cafe-607459933784637460">Cyberdeck Cafe&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;a href="https://crg.eti.br/pt-br/cesar-gimenes/">Cesar Gimenes&lt;/a>&lt;/p></description></item><item><title>GPS do celular na Raspberry Pi</title><link>https://crg.eti.br/pt-br/pub/gps-celular-na-raspberry-pi/</link><pubDate>Thu, 08 Sep 2022 01:46:48 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/gps-celular-na-raspberry-pi/</guid><description>&lt;p>Eu preciso que a &lt;em>Raspberry Pi&lt;/em> que levo na mochila tenha acesso a coordenadas GPS, mas os GPS USB e outros modelos disponíveis para a &lt;em>Raspberry&lt;/em> são muito ruins e caros.&lt;/p>
&lt;p>A solução é usar o GPS do celular e compartilhar os dados com o resto do equipamento, isso tem várias vantagens, o GPS do celular é ótimo, geralmente ele já encontrou alguns satélites e, além disso, já tenho ele no celular evitando que eu tenha que fazer mais uma compra.&lt;/p></description></item><item><title>tr - Utilitário para substituição de caracteres</title><link>https://crg.eti.br/pt-br/pub/tr-substituindo-caracteres/</link><pubDate>Sun, 28 Aug 2022 18:42:40 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/tr-substituindo-caracteres/</guid><description>&lt;p>Este é um utilitário simples e muito útil, basicamente o &lt;code>tr&lt;/code> filtra strings um carácter por vez e se usado corretamente é inclusive compatível com UTF-8.&lt;/p>
&lt;p>O filtro dos caracteres é definido pelos parâmetros e para facilitar  você pode usar &lt;em>classes&lt;/em> de caracteres, por exemplo, &lt;code>[:upper:]&lt;/code> para todas as letras maiúsculas ou &lt;code>[:cntrl:]&lt;/code> para todos os caracteres de controle.&lt;/p>
&lt;h2 id="parâmetros">Parâmetros&lt;/h2>
&lt;p>Os parâmetros que mais uso são os seguintes:&lt;/p>
&lt;ul>
&lt;li>&lt;code>-d&lt;/code> &lt;em>delete&lt;/em> para excluir caracteres.&lt;/li>
&lt;li>&lt;code>-s&lt;/code> &lt;em>squeeze&lt;/em> que é bem interessante para excluir sequencias de caracteres duplicados.&lt;/li>
&lt;/ul>
&lt;h2 id="exemplos">Exemplos&lt;/h2>
&lt;p>Converte maiúsculo para minusculo, mas falha com caracteres UTF-8.&lt;/p></description></item><item><title>fmt - Utilitário simples para formatação de textos</title><link>https://crg.eti.br/pt-br/pub/fmt-formatando-texto/</link><pubDate>Tue, 23 Aug 2022 01:04:14 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/fmt-formatando-texto/</guid><description>&lt;p>O utilitário &lt;code>fmt&lt;/code> é um formatador de texto simples e rápido. Seu objetivo é formatar arquivos texto ou strings via stdin para não ultrapassar o tamanho máximo de caracteres por linha definido pelo usuário.&lt;/p>
&lt;p>Inicialmente foi pensado para seu usado em conjunto com o utilitário mail, mas pode ser útil em conjunto com outros programas como vim, por exemplo.&lt;/p>
&lt;p>Principais parâmetros são:&lt;/p>
&lt;ul>
&lt;li>&lt;code>-w&lt;/code> que indica o número de caracteres desejado pro linha.&lt;/li>
&lt;li>&lt;code>-t&lt;/code> que indica o tamanho da tabulação. &lt;/li>
&lt;/ul>
&lt;p>Existem vários outros parâmetros úteis, consulte a &lt;em>manpage&lt;/em> do seu sistema para saber mais.&lt;/p></description></item><item><title>Cliente e servidor socket em Golang, um exemplo de chat.</title><link>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-chat/</link><pubDate>Sun, 21 Aug 2022 09:35:32 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-chat/</guid><description>&lt;p>Esta é a quarta versão do nosso cliente e servidor socket. Nessa versão, fiz algumas melhorias interessantes. Agora, temos um sistema de chat completo com comandos úteis e algumas otimizações.&lt;/p>
&lt;p>O objetivo desta versão é aprimorar o sistema. Removi um dos canais de escrita para enviar os dados diretamente, aumentando a eficiência. Também eliminei a reconexão automática para deixar o código mais limpo, já que adicionei várias novidades.&lt;/p>
&lt;h2 id="servidor">Servidor&lt;/h2>
&lt;p>Vamos às mudanças no servidor.&lt;/p></description></item><item><title>Assembly no macOS M1/ARM64.</title><link>https://crg.eti.br/pt-br/pub/assembly-m1/</link><pubDate>Sun, 14 Aug 2022 11:26:49 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/assembly-m1/</guid><description>&lt;p>A história é a seguinte, eu tinha encontrado uma ótima oferta de dois computadores  do início dos anos 90 ainda usando processadores &lt;a href="https://en.wikipedia.org/wiki/Zilog_Z80">Zilog Z80&lt;/a>, não estavam perfeitos, mas o valor estava ok. &lt;/p>
&lt;p>Daí, um grande amigo, com muito mais bom senso, aconselhou que eu parasse de gastar energia e dinheiro com máquina velha e sugeriu que para aplacar essa febre de nerdisse eu estudasse assembly do ARM, que pelo menos pode ser útil. &lt;/p></description></item><item><title>Cliente e servidor socket em Golang com tratamento de sinais.</title><link>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-signals/</link><pubDate>Fri, 12 Aug 2022 00:30:22 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-signals/</guid><description>&lt;p>Continuando nossa série de artigos sobre cliente/servidor, adicionaremos um novo canal no &lt;a href="../golang-cliente-servidor-socket-ping-pong">exemplo anterior&lt;/a>. Esse canal tratará sinais enviados pelo sistema operacional.&lt;/p>
&lt;p>O sistema operacional envia sinais aos programas para gerenciar processos. Por exemplo, ao pressionar &lt;em>Ctrl+C&lt;/em>, o sistema operacional envia o sinal SIGINT, informando o programa que o usuário deseja interrompê-lo.&lt;/p>
&lt;p>Por padrão, o programa é fechado. Porém, podemos interceptar esse sinal e agir conforme necessário. Neste caso, apenas finalizaremos o programa. Em sistemas reais, esse recurso pode ser usado para salvar informações antes de fechar, encerrar outros processos, fechar conexões e arquivos, entre outros. Esse processo é conhecido como &lt;em>graceful shutdown&lt;/em>.&lt;/p></description></item><item><title>Cliente e servidor socket em Golang com ping e pong.</title><link>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-ping-pong/</link><pubDate>Thu, 11 Aug 2022 00:55:54 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-ping-pong/</guid><description>&lt;p>Continuando o &lt;a href="../golang-cliente-servidor-socket-com-canais-e-goroutines">papo sobre cliente e servidor resiliente&lt;/a>, é hora de aprimorar o servidor e adicionar o envio de mensagens de &lt;em>ping&lt;/em> ou &lt;em>keep alive&lt;/em>.&lt;/p>
&lt;p>Além disso, fizemos melhorias no servidor. Agora, assim como o cliente, ele utiliza goroutines e canais.&lt;/p>
&lt;h2 id="servidor">Servidor&lt;/h2>
&lt;h3 id="lendo-da-conexão">Lendo da Conexão&lt;/h3>
&lt;p>Nesta versão, o servidor utiliza uma goroutine para escrever e outra para ler os dados da conexão com o cliente. Ao usar goroutines e canais dessa forma, é essencial garantir que as goroutines sejam finalizadas corretamente.&lt;/p></description></item><item><title>Cliente e servidor socket em Golang com goroutines e canais.</title><link>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-com-canais-e-goroutines/</link><pubDate>Sun, 07 Aug 2022 23:47:50 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket-com-canais-e-goroutines/</guid><description>&lt;p>Dando continuidade ao &lt;a href="../golang-cliente-servidor-socket">exemplo sobre cliente socket persistente em Golang&lt;/a>, fiz algumas alterações no código-fonte para ilustrar como melhorar nosso código para torná-lo assíncrono. Para isso, usaremos goroutines e canais.&lt;/p>
&lt;h2 id="goroutines-e-canais">Goroutines e Canais&lt;/h2>
&lt;p>Goroutines e canais são recursos avançados da linguagem Go. Goroutines são threads leves gerenciadas pelo próprio runtime da linguagem, e canais permitem a comunicação entre goroutines.&lt;/p>
&lt;p>No nosso caso, usaremos canais para a comunicação entre as goroutines do nosso programa.&lt;/p></description></item><item><title>Cliente e servidor socket em Golang.</title><link>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket/</link><pubDate>Wed, 03 Aug 2022 07:36:17 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-cliente-servidor-socket/</guid><description>&lt;p>No grupo de estudos de Go, surgiu uma dúvida sobre como escrever um cliente persistente que se reconecte a um servidor socket quando a conexão falhar.&lt;/p>
&lt;p>A principal dificuldade das pessoas parece ser entender o conceito de máquina de estados. Por isso, criaremos alguns exemplos de um cliente persistente, começando por uma máquina de estados simples, sem goroutines nem canais.&lt;/p>
&lt;p>Antes disso, criaremos um pequeno servidor socket para nosso cliente se conectar: o famoso echo server.&lt;/p></description></item><item><title>Torne seu Linux mais inseguro e ligeiramente mais rápido</title><link>https://crg.eti.br/pt-br/pub/linux-mais-rapido-menos-seguro/</link><pubDate>Sun, 26 Jun 2022 17:07:57 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/linux-mais-rapido-menos-seguro/</guid><description>&lt;p>Primeiro, é claro que não me responsabilize pelo que você fizer no seu sistema, lembre de que a responsabilidade é toda sua.&lt;/p>
&lt;p>Existem várias estrategias de processamento que apesar de gerarem um ganho substancial de desempenho acabaram por incluir falhas de segurança, o que fiz foi pegar duas maquinas do meu cluster e configurar o &lt;em>kernel&lt;/em> do &lt;em>Linux&lt;/em> para não desativar esses recursos.&lt;/p>
&lt;p>No meu caso que uso Debian eu editei o arquivo &lt;code>/etc/default/grub&lt;/code> adicionando &lt;code>mitigations=off&lt;/code> no final da variável &lt;code>GRUB_CMDLINE_LINUX_DEFAULT&lt;/code>.&lt;/p></description></item><item><title>Area de transferência remota</title><link>https://crg.eti.br/pt-br/pub/area-de-transferencia-remota/</link><pubDate>Tue, 01 Mar 2022 10:36:45 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/area-de-transferencia-remota/</guid><description>&lt;p>&lt;em>Dica:&lt;/em> O comando &lt;code>pbcopy&lt;/code> no Mac é equivalente a &lt;code>xclip -selection clipboard&lt;/code> no Linux. O comando &lt;code>pbpaste&lt;/code> no Mac corresponde a &lt;code>xclip -selection clipboard -o&lt;/code> no Linux. O comando &lt;code>xclip&lt;/code> não funciona porque requer o &lt;a href="https://en.wikipedia.org/wiki/X_Window_System">X Window&lt;/a> instalado.&lt;/p>
&lt;h2 id="copiar-e-colar">Copiar e Colar&lt;/h2>
&lt;p>Eu edito muito código em servidores remotos via SSH, sem interface gráfica, geralmente uso o &lt;a href="https://neovim.io">Neovim&lt;/a>. Seria ótimo poder copiar e colar entre a máquina remota e a local. Colar da máquina local para a remota é simples, pois o terminal já faz isso. Porém, copiar da máquina remota para a local exige um pouco de código.&lt;/p></description></item><item><title>Acelerando o Site</title><link>https://crg.eti.br/pt-br/pub/acelerando-o-site/</link><pubDate>Sun, 30 Jan 2022 16:00:03 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/acelerando-o-site/</guid><description>&lt;p>Para compartilhar meus artigos usando &lt;a href="https://ipfs.io">IPFS&lt;/a> é interessante fazer com que o CSS e as imagens fossem inseridas no HTML, dessa forma seria apenas um arquivo para compartilhar.&lt;/p>
&lt;p>Inserir o CSS foi a parte mais simples, apenas coloquei o CSS diretamente no modelo do site usando a &lt;em>tag&lt;/em> &lt;code>&amp;lt;style&amp;gt;&amp;lt;/style&amp;gt;&lt;/code>, e apenas embute o CSS já gerou um ganho interessante de velocidade.&lt;/p>
&lt;p>Eu uso o &lt;a href="https://gohugo.io">HUGO&lt;/a> como &lt;em>framework&lt;/em> para geração automática do site, o HUGO funciona convertendo páginas escritas em &lt;em>Markdown&lt;/em>, mas a mesma ideia pode ser usada não importa como o site é feito, mesmo se escrito a mão, direto no HTML. Mas com o HUGO e um pouco de programação foi simples automatizar meu template e fazer com que as imagens fossem convertidas para &lt;em>Base64&lt;/em> e inseridas na página automaticamente.&lt;/p></description></item><item><title>Como estender o git</title><link>https://crg.eti.br/pt-br/pub/git-como-estender/</link><pubDate>Mon, 25 Oct 2021 14:20:09 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/git-como-estender/</guid><description>&lt;p>O git é uma ferramenta extremamente flexível e muito simples de se estender e criar funcionalidades. Para criar comandos basta criar um executável com o nome git-&lt;strong>comando&lt;/strong> (&lt;em>git traço seguido pelo nome do comando&lt;/em>). &lt;/p>
&lt;p>Qualquer executável acessível no PATH com esse padrão de nome vai ser chamado pelo git. Para começar com um exemplo simplesi, vamos para o tradicional &amp;ldquo;hello world&amp;rdquo;, salve o exemplo abaixo com o nome &lt;code>git-hello&lt;/code> em um diretório no PATH.&lt;/p></description></item><item><title>Headless VirtualBox</title><link>https://crg.eti.br/pt-br/pub/headless-virtualbox/</link><pubDate>Sat, 02 Oct 2021 00:25:33 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/headless-virtualbox/</guid><description>&lt;p>&lt;strong>WIP - Este texto é um trabalho em progresso, ainda não registrei todos os exemplos que queria nem revi o texto. Contribuições são bem-vindas.&lt;/strong>&lt;/p>
&lt;p>Continuando com o projeto de montar um &lt;em>cluster&lt;/em> de máquinas, vou precisar de algum sistema de virtualização, porque nem todos os experimentos que quero fazer podem ser feitos apenas com containers. Fiz alguns testes com o &lt;a href="https://www.qemu.org">QEMU&lt;/a>, mas por enquanto é mais prático &lt;em>continuar&lt;/em> com o &lt;a href="https://www.virtualbox.org">VirtualBox&lt;/a>.&lt;/p>
&lt;p>Todo acesso no &lt;em>cluster&lt;/em> é via ssh, então é necessário controlar o VirtualBox via linha de comando usando o utilitário &lt;em>VBoxManage&lt;/em>.&lt;/p></description></item><item><title>Como diminuir o tamanho do container usando multi-stage builds.</title><link>https://crg.eti.br/pt-br/pub/docker-multi-stage-build/</link><pubDate>Thu, 17 Jun 2021 20:52:35 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/docker-multi-stage-build/</guid><description>&lt;p>De vez em quando esbarro com alguma imagem docker enorme em que 99% do tamanho é lixo deixado quando a imagem estava sendo construída. Isso é especialmente ruim quando estamos de executáveis Go que são autocontidos e geralmente não precisam de nenhum recurso externo, nem mesmo a libc.&lt;/p>
&lt;h2 id="multi-stage-builds">multi-stage builds&lt;/h2>
&lt;p>A solução é usar &lt;em>multi-stage builds&lt;/em>, dessa forma você pode ter duas etapas no seu Dockerfile, uma de compilação que baixa o que for necessário, compila o código, etc. e outra que apenas copia os executáveis e os recursos para os locais esperados e nem precisa ser baseada em alguma distribuição, pode ser uma imagem &lt;em>scretch&lt;/em> que reduz ainda mais o tamanho final.&lt;/p></description></item><item><title>auto-cpufreq ajustando dinamicamente a frequência da CPU</title><link>https://crg.eti.br/pt-br/pub/auto-cpufreq/</link><pubDate>Thu, 03 Jun 2021 21:24:42 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/auto-cpufreq/</guid><description>&lt;p>O &lt;a href="https://github.com/AdnanHodzic/auto-cpufreq">auto-cpufreq&lt;/a> otimiza a frequência da CPU e reage bem rapidamente, é muito bom para esticar a carga da bateria para quem usa um notebook Linux.&lt;/p>
&lt;p>No meu caso eu estou usando para manter meu pequeno servidor doméstico em uma temperatura mais amena e na prática não senti impacto, tem um pouco de latência quando a máquina está &amp;ldquo;fria&amp;rdquo; e do nada eu inicio algum processo pesado, como subir uma sessão SSH+mosh+zsh.&lt;/p></description></item><item><title>Primeiros passos na configuração de um novo servidor.</title><link>https://crg.eti.br/pt-br/pub/configurando-novo-servidor/</link><pubDate>Mon, 03 May 2021 18:30:30 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/configurando-novo-servidor/</guid><description>&lt;p>Quando subo uma máquina nova sempre executo alguns comandos e faço algumas configurações, muita coisa já esta pronta nos meus &lt;a href="https://github.com/crgimenes/dotfiles">dotfiles&lt;/a> mas sempre tem muita coisa personalizada para fazer.&lt;/p>
&lt;p>A primeira coisa é obter acesso ssh, ter certeza que as senhas de root não são as default.&lt;/p>
&lt;p>Em seguida dou acesso de sudo para meu usuário caso já não tenha.&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-fallback" data-lang="fallback">&lt;span style="display:flex;">&lt;span>usermod -aG sudo ${USER}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Se for uma máquina na rede local eu configuro ela para usar &lt;a href="https://crg.eti.br/pt-br/pub/zero-configuration-network-no-debian/">zero configuration network&lt;/a>, uma forma muito mais conveniente de acessar a máquina principalmente em redes IPv6. caso contrário esse é um bom momento para adicionar a maquina em um domínio.&lt;/p></description></item><item><title>O manual do UNIX</title><link>https://crg.eti.br/pt-br/pub/o-manual-do-unix/</link><pubDate>Wed, 10 Feb 2021 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/o-manual-do-unix/</guid><description>&lt;p>Em 3 de novembro de 1971, foi lançada a primeira versão do &lt;a href="https://www.bell-labs.com/usr/dmr/www/1stEdman.html">Unix Programmer&amp;rsquo;s Manual&lt;/a>, comumente conhecido como man pages.&lt;/p>
&lt;p>Você pode baixar em PDF ou PostScript na &lt;a href="https://www.bell-labs.com/usr/dmr/www/">página de Dennis Ritchie na Bell Labs&lt;/a>, mantida pela Nokia por motivos históricos.&lt;/p>
&lt;p>É interessante como os comandos do UNIX não mudaram muito ao longo dos anos. Se você é usuário de Linux ou BSD, certamente reconhecerá a maioria deles. Também é fantástico como uma ideia tão simples pode ser tão incrivelmente útil.&lt;/p></description></item><item><title>Dica do comando find</title><link>https://crg.eti.br/pt-br/pub/dica-do-comando-find/</link><pubDate>Wed, 14 Oct 2020 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/dica-do-comando-find/</guid><description>&lt;p>Eu uso bastante o comando find para procurar por arquivos, sejá em scripts bash seja na linha de comando.&lt;/p>
&lt;p>Um truque interessante é excluir alguns arquivos da lista, por exemplo hoje eu precisei procurar por todos os arquivos &amp;ldquo;.md&amp;rdquo; mas queria excluir todos os iniciados com underline e também o arquivo &amp;ldquo;default.md&amp;rdquo;.&lt;/p>
&lt;p>Para fazer isso usei o parametro &lt;em>-not&lt;/em> antes do parametro &lt;em>-name&lt;/em> como no exemplo abaixo.&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>find . &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> -type f &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 &lt;span style="color:#0a3069">&amp;#39;*.md&amp;#39;&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> -not -name &lt;span style="color:#0a3069">&amp;#39;_*md&amp;#39;&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> -not -name &lt;span style="color:#0a3069">&amp;#39;default.md&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="excluindo-arquivos">Excluindo arquivos&lt;/h2>
&lt;p>No meu caso eu queria excluir os arquivos mantendo os arquivos todo o resto da estrutura então usei a linha de comando abaixo, com a unica substituição do comando &lt;em>echo&lt;/em> por &lt;em>rm&lt;/em>. Claro que eu deixei o comando &lt;em>echo&lt;/em> no exemplo para deixar mais seguro para quem quer só copiar o comando e testar.&lt;/p></description></item><item><title>Configurando timeout para requisições HTTP em Golang</title><link>https://crg.eti.br/pt-br/pub/go-http-timeout/</link><pubDate>Sun, 04 Oct 2020 10:41:09 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-http-timeout/</guid><description>&lt;p>Por padrão Go não tem timeout para requisições HTTP, isso pode acarretar vários problemas e vulnerabilidades, por exemplo, um ataque DOS pode simplesmente abrir várias conexões com seu servidor.&lt;/p>
&lt;p>Para resolver crie uma instancia da &lt;em>struct&lt;/em> http.Server e preencha os campos WriteTimeout e ReadTimeout com os tempos que achar adequados.&lt;/p>
&lt;p>Veja o exemplo de código.&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-golang" data-lang="golang">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#cf222e">func&lt;/span> &lt;span style="color:#6639ba">main&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:#1f2328">mux&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">NewRouter&lt;/span>&lt;span style="color:#1f2328">().&lt;/span>&lt;span style="color:#6639ba">StrictSlash&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#cf222e">true&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:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">HandleFunc&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;/&amp;#34;&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#1f2328">mainHandler&lt;/span>&lt;span style="color:#1f2328">)&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:#1f2328">srv&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#0550ae">&amp;amp;&lt;/span>&lt;span style="color:#1f2328">http&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">Server&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">Handler&lt;/span>&lt;span style="color:#1f2328">:&lt;/span> &lt;span style="color:#1f2328">r&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">Addr&lt;/span>&lt;span style="color:#1f2328">:&lt;/span> &lt;span style="color:#0a3069">&amp;#34;:8000&amp;#34;&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">WriteTimeout&lt;/span>&lt;span style="color:#1f2328">:&lt;/span> &lt;span style="color:#0550ae">15&lt;/span> &lt;span style="color:#0550ae">*&lt;/span> &lt;span style="color:#1f2328">time&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">Second&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">ReadTimeout&lt;/span>&lt;span style="color:#1f2328">:&lt;/span> &lt;span style="color:#0550ae">15&lt;/span> &lt;span style="color:#0550ae">*&lt;/span> &lt;span style="color:#1f2328">time&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">Second&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>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#1f2328">log&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Println&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#0a3069">&amp;#34;Listen at port :8000&amp;#34;&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">log&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">Fatal&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#1f2328">srv&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#6639ba">ListenAndServe&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>Isso vai definir os tempos de timeout default para todas as requisições HTTP.&lt;/p></description></item><item><title>Controle de sessão em Golang como Gorilla sessions</title><link>https://crg.eti.br/pt-br/pub/go-controle-de-sessao/</link><pubDate>Sat, 03 Oct 2020 22:38:09 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-controle-de-sessao/</guid><description>&lt;p>Controle de sessão é um conceito bastante antigo, basicamente se usa cookies para guardar alguns dados da sessão do usuário, por segurança geralmente só preservamos no cookie um UUID o mais aleatório possível, que o servidor usa para consultar outros dados, como por exemplo saber qual usuário esta logado.&lt;/p>
&lt;p>O UUID precisa ser o mais aleatório possível porque se alguém conseguir prever qual será o próximo UUID é possível roubar a sessão de um usuário legitimo.&lt;/p></description></item><item><title>Descobrindo ip com Golang</title><link>https://crg.eti.br/pt-br/pub/descobrindo-ip-com-golang/</link><pubDate>Sat, 23 May 2020 10:45:43 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/descobrindo-ip-com-golang/</guid><description>&lt;p>Recentemente eu esbarrei com um problema interessante, eu precisava subir um pequeno serviço REST para gerenciar alguns hardwares, tudo sem contato humano e também com várias interfaces de rede.&lt;/p>
&lt;p>Em um determinado momento meu sistema tem que subir um serviço auxiliar e informar o cliente em que ip e porta ele deveria acessar. Normalmente isso seria feito com um arquivo de configuração em algum lugar, mas um requisito é que eu não podia presumir meu ip porque ele poderia vir de qualquer uma das interfaces de rede e deixar tudo isso parametrizado ficaria complexo demais.&lt;/p></description></item><item><title>Diferenças entre slice e array em Go</title><link>https://crg.eti.br/pt-br/pub/diferencas-entre-slices-e-arrays-golang/</link><pubDate>Tue, 14 Apr 2020 11:11:33 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/diferencas-entre-slices-e-arrays-golang/</guid><description>&lt;h2 id="array">Array&lt;/h2>
&lt;p>Array em Go sempre tem tamanho fixo.&lt;/p>
&lt;p>Quando você adiciona um novo elemento em um array o que acontece internamente é que um novo array é criado e os itens antigos e novos são copiados para esse novo array. Eventualmente o espaço opupado pelo array antigo será liberado pelo garbage collector. Então é importante, sempre que possível, declarar o array com o tamanho máximo que ele vai precisar e evitar adicionar itens, principalmente em loop.&lt;/p></description></item><item><title>Os problemas programando em Golang</title><link>https://crg.eti.br/pt-br/pub/problemas-programando-em-golang/</link><pubDate>Sun, 01 Mar 2020 11:11:33 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/problemas-programando-em-golang/</guid><description>&lt;p>Eu amo Go. Escolho Go para muitos dos meus projetos. Ela é simples e robusta, com ampla documentação, diversos exemplos e uma biblioteca padrão extensa, focada em resolver problemas atuais. Sem dúvida, é uma excelente linguagem.&lt;/p>
&lt;p>Entretanto, nada é perfeito. Golang tem seus problemas, assim como qualquer outra linguagem. Alguns serão resolvidos conforme o compilador evolui. Outros, o programador precisa estar atento. Vamos ver alguns dos mais comuns. Alguns problemas mencionados aqui não são exclusivos do Go, mas sim decorrentes de um design de código ruim, que já encontrei diversas vezes e vale a pena mencionar.&lt;/p></description></item><item><title>Shadow de variáveis em Golang</title><link>https://crg.eti.br/pt-br/pub/golang-shadow-variaveis/</link><pubDate>Sat, 15 Feb 2020 20:12:16 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/golang-shadow-variaveis/</guid><description>&lt;p>Golang é uma linguagem de programação fácil de usar e que ajuda a evitar muitos dos erros comuns.&lt;/p>
&lt;p>Mas um erro que é fácil de cometer em Go e que ainda não gera warnings do compilador é shadow de variáveis.&lt;/p>
&lt;p>Shadow é quando você declara uma variável em um bloco de código e em um bloco aninhado declara novamente a variável.&lt;/p>
&lt;p>Daí você faz alterações no valor da variável acreditando que esta atualizando a variável do bloco de hierarquia superior mas na verdade esta alterando apenas a variável do bloco atual.&lt;/p></description></item><item><title>Primeiros passos com assembly</title><link>https://crg.eti.br/pt-br/pub/primeiros-passos-com-assembly/</link><pubDate>Sat, 08 Feb 2020 20:12:16 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/primeiros-passos-com-assembly/</guid><description>&lt;p>Toda quinta-feira, um grupo de programadores e eu nos reunimos para conversar sobre Golang no &lt;a href="https://github.com/crgimenes/grupo-estudos-golang">Grupo de Estudos de Go&lt;/a>. Devemos mudar o nome para &lt;em>Grupo de Estudos de Tecnologia&lt;/em> porque discutimos todos os assuntos relacionados.&lt;/p>
&lt;p>Um tema recorrente é programação em assembly. Várias vezes, discutimos iniciar demonstrações e brincadeiras carregadas via setor de boot, conhecidas como &amp;ldquo;boot sector games&amp;rdquo;.&lt;/p>
&lt;p>Além de ser divertido, é uma boa forma de ensinar como o computador funciona internamente. Conceitos como velocidade de acesso, cache Lx e outros são abstratos em linguagens de alto nível.&lt;/p></description></item><item><title>Web Scraping com Golang</title><link>https://crg.eti.br/pt-br/pub/web-scraping-com-golang/</link><pubDate>Mon, 23 Sep 2019 08:16:28 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/web-scraping-com-golang/</guid><description>&lt;p>Recentemente precisei extrair algumas informações de um site, meu plano era simples, verificar a URL que o formulário de pesquisa apontava e fazer a requisição diretamente pelo meu programa, daí usar o package &lt;a href="https://github.com/PuerkitoBio/goquery">goquery&lt;/a> fazer parser dos resultados e pegar os dados que eu queria.&lt;/p>
&lt;p>Claro que não foi fácil assim. O site que eu queria crawlear era repleto de JavaScripts que interferiam com o formulário, com os cookies e com basicamente tudo.&lt;/p></description></item><item><title>Um pequeno emulador da CPU 8086</title><link>https://crg.eti.br/pt-br/pub/assembly-emulador-8086/</link><pubDate>Tue, 16 Jul 2019 08:16:28 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/assembly-emulador-8086/</guid><description>&lt;h2 id="emulador-8086-escrito-em-c">Emulador 8086 escrito em C&lt;/h2>
&lt;p>A primeira coisa que é preciso deixar claro é que esse não é um &lt;a href="https://en.wikipedia.org/wiki/Emulator">emulador&lt;/a> completo, o objetivo é apenas interpretar um hello world. Claro, é possível pegar esse esqueleto e expandir até se tornar um emulador completo.&lt;/p>
&lt;p>Eu estava entediado esperando meus amigos aparecerem na &lt;a href="https://brasil.campus-party.org">Campus Party&lt;/a> de 2016, encontrei a mesa que estava separada para a galera de &lt;a href="https://en.wikipedia.org/wiki/Hackerspace">hackerspace&lt;/a> e fiquei esperando mas como não tinha nenhuma palestra aquele horário nem nada que eu quisesse participar eu precisava de algo para matar o tempo.&lt;/p></description></item><item><title>Home Office, Minha Experiencia Trabalhando em Casa</title><link>https://crg.eti.br/pt-br/pub/home-office/</link><pubDate>Tue, 09 Jul 2019 20:12:16 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/home-office/</guid><description>&lt;p>Aqui vamos ver algumas coisas da minha experiência trabalhando em home-office e vou dar algumas dicas de como eu resolvi problemas comuns que todo mundo que quer trabalhar com tecnologia longe do escritório vai enfrentar.&lt;/p>
&lt;p>Eu sou um veterano quando o assunto é trabalho remoto. Comecei no fim dos anos 90, na época eu trabalhava em uma empresa com uma administração bastante arrojada e moderna principalmente para o Brasil da época. Na época eu era um jovem programador com muito para aprender ainda.&lt;/p></description></item><item><title>O BASIC ainda esta vivo e chutando</title><link>https://crg.eti.br/pt-br/pub/basic-ainda-esta-vivo/</link><pubDate>Mon, 08 Jul 2019 20:12:16 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/basic-ainda-esta-vivo/</guid><description>&lt;p>Em minha pesquisa sobre implementações em BASIC, encontrei algumas coisas interessantes. É incrível como uma linguagem antiga e com tantos problemas ainda existe. Ainda é possível encontrar compiladores comerciais sendo desenvolvidos para ela.&lt;/p>
&lt;p>Sim, apesar de ser fã e adorar brincar com BASIC pela nostalgia e diversão, não dá para negar que BASIC causa mais problemas do que benefícios. (Na minha opinião)&lt;/p>
&lt;p>Claro, fazia sentido ter uma linguagem extremamente simples quando o BASIC nasceu, em 1964. Máquinas com poucos recursos e o propósito de ser uma linguagem para iniciantes. BASIC significa &lt;a href="https://en.wikipedia.org/wiki/BASIC">Beginner’s All-Purpose Symbolic Instruction Code&lt;/a>&lt;/p></description></item><item><title>Erro difícil com interfaces e switch case em Go</title><link>https://crg.eti.br/pt-br/pub/erro-na-ordem-do-switch/</link><pubDate>Sun, 24 Feb 2019 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/erro-na-ordem-do-switch/</guid><description>&lt;p>Veja o vídeo falando desse erro no &lt;a href="https://www.youtube.com/watch?v=v3h024EtxCU">Grupo de Estudos de Golang&lt;/a>.&lt;/p>
&lt;p>Golang é uma linguagem bem fácil de programar e que tem poucas armadilhas para o programador. A maioria das coisas que podem dar errado são pegas pelo compilador ou por alguma das muitas ferramentas de análise estática que ajudam a manter nosso código &lt;em>quase&lt;/em> livre de bugs.&lt;/p>
&lt;p>Mas existem situações em que mesmo essas ferramentas tem dificuldade nos alertar porque não da para saber o que o programador queria que fosse o resultado do programa. Isso geralmente acontece usando os recursos mais divertidos da linguagem como &lt;em>switch&lt;/em>, &lt;em>interfaces&lt;/em>, &lt;em>canais&lt;/em> e &lt;em>goroutines&lt;/em>.&lt;/p></description></item><item><title>Cobertura de testes unitários em Go</title><link>https://crg.eti.br/pt-br/pub/cobertura-de-testes/</link><pubDate>Wed, 13 Feb 2019 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/cobertura-de-testes/</guid><description>&lt;p>Testes unitários são incrivelmente importantes, mesmo para uma linguagem compilada como Golang eles são fundamentais.&lt;/p>
&lt;p>Felizmente, hoje em dia, a maioria das linguagens de programação tem uma bela variedade de ferramentas para teste unitário. Go vem com algumas ferramentas surpreendentes, não apenas para fazer os testes mas também para analisar o código em busca de falhas na cobertura, etc.&lt;/p>
&lt;p>Uma forma visual e rápida para analisar a cobertura de testes é fazer um script com &lt;code>go tool cover&lt;/code> que pode ser colocado na carga do &lt;code>zsh&lt;/code> ou no &lt;code>bash&lt;/code> e torna muito simples fazer essa inspeção do código.&lt;/p></description></item><item><title>Quine implementado em Golang</title><link>https://crg.eti.br/pt-br/pub/quine-em-golang/</link><pubDate>Tue, 12 Feb 2019 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/quine-em-golang/</guid><description>&lt;h2 id="imprimindo-seu-próprio-código-fonte">Imprimindo seu próprio código-fonte&lt;/h2>
&lt;p>Quine é um programa que consegue imprimir seu código-fonte na saída padrão. O nome é em homenagem ao matemático e filosofo &lt;a href="https://en.wikipedia.org/wiki/Willard_Van_Orman_Quine">Willard Van Orman Quine&lt;/a>.&lt;/p>
&lt;p>Existem exemplos de &lt;a href="https://en.wikipedia.org/wiki/Quine_%28computing%29">Quine&lt;/a> escritos para várias linguagens de programação, é um exercício interessante tentar escrever a sua versão e um belo desafio.&lt;/p>
&lt;p>Veja bem, a regra é que não pode simplesmente abrir seu próprio código-fonte e imprimir, isso seria trapaça, o que precisa fazer é que seu código seja gere na saída padrão uma versão de si sem ler de lugar nenhum.&lt;/p></description></item><item><title>PostgreSQL via SSL com Golang</title><link>https://crg.eti.br/pt-br/pub/postgresql-ssl-golang/</link><pubDate>Fri, 04 Jan 2019 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/postgresql-ssl-golang/</guid><description>&lt;h2 id="criando-o-certificado">Criando o certificado&lt;/h2>
&lt;p>Primeiro vamos criar um certificado de testes, claro que quando for usar em produção você deve usar um certificado gerado por uma entidade certificadora reconhecida.&lt;/p>
&lt;p>Com o comando abaixo vamos criar dois arquivos &lt;code>server.crt&lt;/code> e &lt;code>server.key&lt;/code> que vamos usar para configurar o &lt;a href="https://www.postgresql.org">PostgreSQL&lt;/a>.&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>openssl req -new -x509 -days &lt;span style="color:#0550ae">365&lt;/span> -nodes -text -out server.crt &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> -keyout server.key -subj &lt;span style="color:#0a3069">&amp;#34;/CN=example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="configurando-postgresql">Configurando PostgreSQL&lt;/h2>
&lt;p>Edite o arquivo postgresql.conf para ativar o uso da chave SSL.&lt;/p></description></item><item><title>Unix Domain Socket com Golang</title><link>https://crg.eti.br/pt-br/pub/unix-domain-socket-golang/</link><pubDate>Thu, 06 Dec 2018 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/unix-domain-socket-golang/</guid><description>&lt;ul>
&lt;li>&lt;em>Unix Domain Sockets&lt;/em> ou &lt;em>&lt;a href="https://en.wikipedia.org/wiki/Inter-process_communication">IPC&lt;/a> Socket&lt;/em>&lt;/li>
&lt;/ul>
&lt;p>&lt;em>Unix Domain Sockets&lt;/em> é uma forma prática e segura de trocar informações entre processos. Essa forma de &lt;em>IPC&lt;/em> (Inter-process communication) usa um arquivo como endereço em vez de um IP e uma porta, como na comunicação via rede.&lt;/p>
&lt;p>É importante lembrar que o servidor gerencia o arquivo. Se o arquivo não existir, o servidor o cria automaticamente. Se o arquivo já existir, você receberá um erro como &amp;ldquo;bind: address already in use&amp;rdquo;. Isso significa que o servidor não pode reutilizar o arquivo existente. Portanto, é correto desligar o servidor de forma elegante, fechar e apagar o arquivo antes de finalizar o servidor. Dependendo do sistema, pode ser interessante verificar se o arquivo existe e apagá-lo antes de iniciar o servidor.&lt;/p></description></item><item><title>Um JSON lint em Golang</title><link>https://crg.eti.br/pt-br/pub/json-lint-golang/</link><pubDate>Fri, 30 Nov 2018 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/json-lint-golang/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=VXVZE5SYMiM">aqui&lt;/a>.&lt;/p>
&lt;h2 id="um-json-lint-em-golang">Um JSON lint em Golang&lt;/h2>
&lt;p>Esse é um pequeno utilitário de linha de comando para validar e formatar JSON que também pode ser usado como pacote, a ideia inicial era criar um parser para validar o JSON mas não foi necessário, o próprio Golang traz todas as informações que precisamos no erro inclusive o offset do erro e dai foi simples mostrar os erros de forma mais completa inclusive indicando com uma seta exatamente onde esta o erro.&lt;/p></description></item><item><title>Trafegando dados entre middleware http usando contexto em Golang</title><link>https://crg.eti.br/pt-br/pub/middleware-em-golang/</link><pubDate>Fri, 09 Nov 2018 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/middleware-em-golang/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=Xyj-dQvfvq0">aqui&lt;/a>.&lt;/p>
&lt;h2 id="trafegando-dados-entre-middleware">Trafegando dados entre middleware&lt;/h2>
&lt;p>Já vimos &lt;a href="https://www.youtube.com/watch?v=aQGRh7ECgwg">como funciona um middleware HTTP&lt;/a> e agora vamos ver como passar informação entre os middlewares. Isso é usado por exemplo para passar as credenciais de um usuário para o próximo middleware e qualquer outra informação que seja coletada em algum dos middlewares e você queria passar para frente.&lt;/p>
&lt;p>Antes de mais nada vamos fazer um exemplo para mostrar da forma mais clara possível quando os middlewares são executados, isso é muito importante porque erros no entendimento dessa ordem de execução é uma incrível fonte de bugs. No exemplo abaixo colocamos mensagens no terminal toda vez que um middleware é carregado e descarregado. E é sempre bom reforçar isso vai acontecer na mesma ordem em que eles foram registrados.&lt;/p></description></item><item><title>Como fazer HTTP middleware em Golang tanto usando Negroni como usando a biblioteca padrão</title><link>https://crg.eti.br/pt-br/pub/middleware-usando-negroni/</link><pubDate>Fri, 02 Nov 2018 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/middleware-usando-negroni/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=aQGRh7ECgwg">aqui&lt;/a>.&lt;/p>
&lt;p>Usar &lt;a href="https://en.wikipedia.org/wiki/Middleware">middleware&lt;/a> HTTP são muito úteis para evitar duplicidade de código quando você tem vários endpoints na sua aplicação, por exemplo se você quiser ter certeza que as credenciais do usuário foram verificadas, ou que o conteúdo foi comprimido, e assim por diante.&lt;/p>
&lt;p>A coisa mais importante que se deve lembrar é que cada middleware vai ser chamado na ordem que foi registrado, então por exemplo podemos ter um middleware que tem a responsabilidade de preparar o ambiente, como abrir o banco de dados ou preparar o controle de sessão que vem antes do middleware que valida as credenciais do usuário.&lt;/p></description></item><item><title>Usando goto e label em Go</title><link>https://crg.eti.br/pt-br/pub/goto-label-em-golang/</link><pubDate>Fri, 26 Oct 2018 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/goto-label-em-golang/</guid><description>&lt;p>A instrução &lt;em>goto&lt;/em> tem fama negativa. No tempo do BASIC programadores não tinham muitas opções e abusavam do comando &lt;em>goto&lt;/em> e criaram códigos confusos. Linguagens modernas, como Go, usam goto com critério e melhoram a clareza do código.&lt;/p>
&lt;p>Go permite que os comandos &lt;em>break&lt;/em> e &lt;em>continue&lt;/em> usem labels. Use labels para sair de loops aninhados com &lt;em>break&lt;/em> dar &lt;em>continue&lt;/em> em um loop específico. Usar &lt;em>break&lt;/em> ou &lt;em>continue&lt;/em> com &lt;em>labels&lt;/em> equivale a usar goto.&lt;/p></description></item><item><title>Um sistema de mensageria extremamente rápido com NATS e Golang</title><link>https://crg.eti.br/pt-br/pub/mensageria-com-nats-e-golang/</link><pubDate>Fri, 19 Oct 2018 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/mensageria-com-nats-e-golang/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=NBi0r7QOJSs">aqui&lt;/a>.&lt;/p>
&lt;h2 id="mensageria-com-nats">mensageria com NATS&lt;/h2>
&lt;p>Para quem precisa que vários sistemas se comuniquem entre si e precisa de velocidade e simplicidade o &lt;a href="https://nats.io">NATS&lt;/a> é uma grande ajuda. Uma das características mais interessantes é a incrível velocidade e um protocolo simples que pode ser facilmente implementado faz com que o NATS seja usado desde para IoT com bibliotecas cliente escritas até mesmo para Arduino quando para comunicação entre serviços muito maiores. Também é muito usado para aplicações mobile por pelo mesmo motivo, protocolo simples e rápido. É uma alternativa muito interessante ao &lt;a href="https://mqtt.org">MQTT&lt;/a> e é implementado em Go. :D&lt;/p></description></item><item><title>Protocol Buffers</title><link>https://crg.eti.br/pt-br/pub/protobuf-com-golang/</link><pubDate>Thu, 20 Sep 2018 08:19:09 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/protobuf-com-golang/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=XzSgREcg_sU">aqui&lt;/a>.&lt;/p>
&lt;p>Este é o primeiro de uma série de tutoriais rápidos onde planejo cobrir o uso de &lt;a href="https://grpc.io">gRPC&lt;/a> e vários aspectos como testes, TLS, boas práticas e muito mais.&lt;/p>
&lt;p>Para iniciar com gRPC precisamos ir até a base então vamos primeiro falar de &lt;a href="https://developers.google.com/protocol-buffers">Protocol Buffers&lt;/a>.&lt;/p>
&lt;p>Protocol Buffers é uma forma simples e agnóstica com relação à linguagem de se definir uma estrutura de dados, como XML, só que melhor, mais simples e mais rápido, muito mais rápido.&lt;/p></description></item><item><title>ssh - Usando chaves de acesso</title><link>https://crg.eti.br/pt-br/pub/ssh-usando-chave/</link><pubDate>Sun, 09 Sep 2018 08:19:09 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/ssh-usando-chave/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=f-4R_PNEFT4">aqui&lt;/a>.&lt;/p>
&lt;p>Acessar servidores via SSH usando um conjunto de chaves publica/privada é mais seguro e prático, principalmente mais seguro, além de facilitar a automação de várias tarefas.&lt;/p>
&lt;h2 id="criando-as-chaves">Criando as chaves&lt;/h2>
&lt;p>Primeiro crie as chaves com o seguinte comando:&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>mkdir ~/.ssh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ssh-keygen
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Precisa fazer isso apenas uma vez na máquina cliente e um conjunto de chaves será gerado, você pode definir o nome do arquivo que por padrão seria &lt;code>id_rsa&lt;/code> para a chave secreta e &lt;code>id_rsa.pub&lt;/code> para a chave publica.&lt;/p></description></item><item><title>JSON, criando seu próprio Marshal e Unmarshal</title><link>https://crg.eti.br/pt-br/pub/json-parser/</link><pubDate>Thu, 06 Sep 2018 08:19:09 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/json-parser/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=ALlzgQfXVFo">aqui&lt;/a>.&lt;/p>
&lt;p>O formato de data padrão do Postgres é incompatível com o formato padrão do Golang e o nosso sistema usa muito JSON para tanto mandar como receber informações do banco de dados.&lt;/p>
&lt;p>Ter que lembrar toda hora de fazer o parser da data para o formato correto simplesmente não é pratico, é muito melhor ensinar o Golang como lidar com data e hora no bom e velho formato ISO 8601.&lt;/p></description></item><item><title>Interface como um contrato</title><link>https://crg.eti.br/pt-br/pub/interface-contrato/</link><pubDate>Thu, 30 Aug 2018 20:05:18 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/interface-contrato/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=ck9rGF0tfRE">aqui&lt;/a>.&lt;/p>
&lt;p>Falamos desse mesmo tema na nossa lista de exemplos do grupo de estudos sobre interfaces mas vamos isso foi la no longínquo ano de 2016 então vamos tentar fazer um novo exemplo para mostrar como usar uma interface como um contrato que permite você passar tipos diferentes para uma função ou aceitar tipos diferentes em uma interface desde que ele aceite implemente o &lt;code>contrato&lt;/code> que em outras palavras significa implementar as funções descritas na interface.&lt;/p></description></item><item><title>Usando VPN no macOS</title><link>https://crg.eti.br/pt-br/pub/proton-vpm/</link><pubDate>Sat, 25 Aug 2018 20:05:18 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/proton-vpm/</guid><description>&lt;p>Como qualquer ferramenta, usar uma &lt;a href="https://pt.wikipedia.org/wiki/Rede_privada_virtual">VPN&lt;/a> só será efetivo se você souber exatamente qual problema quer resolver com ela. Existem pessoas que querem manter seu trafego pela internet anônimo, outras querem proteger seus dados, e por aí vai. O meu uso é bem específico, alguns provedores de acesso à internet estão bloqueando portas importantes que uso para acessar serviços, por exemplo, um famoso provedor daqui de São Paulo esta bloqueando a porta TCP 22 que usamos para acessar o SSH, note que não é o caso do provedor bloquear conexões de entrada que já era comum, mas de saída, ou seja, usar qualquer serviço que dependa de SSH como o &lt;a href="https://github.com/crgimenes">GitHub&lt;/a> por exemplo ou acessar uma máquina hospedada na Computer Engine do Google Cloud Platform fica impossível.&lt;/p></description></item><item><title>Interface vazia</title><link>https://crg.eti.br/pt-br/pub/interface-vazia/</link><pubDate>Thu, 23 Aug 2018 20:05:18 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/interface-vazia/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=yBTzaVwqvng">aqui&lt;/a>.&lt;/p>
&lt;p>Interface vazia é um tipo que aceita qualquer coisa, você pode passar o que quiser como parâmetros de função ou variáveis do tipo &lt;code>interface{}&lt;/code>.&lt;/p>
&lt;p>Parece muito pratico a primeira vista mas quando usamos &lt;code>interface{}&lt;/code> estamos jogando pela janela a validação de tipos feita em tempo de compilação e perdemos uma das grandes vantagens de uma linguagem compilada de tipagem forte e estática.&lt;/p>
&lt;p>E como a checagem de tipo não vai acontecer em tempo de compilação é sua responsabilidade checar se esta recebendo o tipo certo em tempo de execução.&lt;/p></description></item><item><title>JSON Dicas e Truques</title><link>https://crg.eti.br/pt-br/pub/json-golang/</link><pubDate>Thu, 16 Aug 2018 20:05:18 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/json-golang/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=0PJ1YqO3wjI">aqui&lt;/a>.&lt;/p>
&lt;h2 id="convertendo-e-validando-json">Convertendo e validando JSON&lt;/h2>
&lt;p>É sempre bom saber se o JSON é valido antes, isso poupa tempo de debug procurando um problema que não esta no seu código, para isso uma boa ferramenta on-line é o &lt;a href="https://jsonlint.com">JSONLint&lt;/a>&lt;/p>
&lt;p>Outra ferramenta on-line muito boa é o &lt;a href="https://mholt.github.io/json-to-go">JSON-to-Go&lt;/a> para converter arquivos JSON em struct Go, ele não vai converter partes repetitivas em sub-structs mas ajuda muito, principalmente quando a estrutura é muito grande e complexa.&lt;/p></description></item><item><title>MS-DOS, APM com C e Assembly</title><link>https://crg.eti.br/pt-br/pub/apm-msdos-assembly/</link><pubDate>Sun, 05 Aug 2018 20:05:18 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/apm-msdos-assembly/</guid><description>&lt;p>Veja o vídeo deste arquivo &lt;a href="https://www.youtube.com/watch?v=GTIIId3enis">aqui&lt;/a>.&lt;/p>
&lt;p>Para brincar de retrocomputação, eu uso o &lt;a href="https://www.virtualbox.org">VirtualBox&lt;/a> com o &lt;a href="https://pt.wikipedia.org/wiki/MS-DOS">MS-DOS 6.22&lt;/a> e o &lt;a href="https://www.dosbox.com">DOSBox&lt;/a>. Ambos funcionam muito bem, mas a tela fica um pouco melhor no VirtualBox, e o DOSBox é mais rápido e fácil para desenvolver e alternar rapidamente entre sistemas. Por isso, uso os dois.&lt;/p>
&lt;p>No DOSBox, você pode fechar o simulador digitando o comando &lt;code>exit&lt;/code>. Isso fecha uma sessão do interpretador de comandos e, se for a última sessão, fecha o próprio DOSBox. É conveniente porque não precisa usar o mouse e se comporta mais como um terminal.&lt;/p></description></item><item><title>Acessando Dropbox com Golang</title><link>https://crg.eti.br/pt-br/pub/dropbox-com-golang/</link><pubDate>Thu, 02 Aug 2018 20:05:18 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/dropbox-com-golang/</guid><description>&lt;p>Precisei de um pacote Golang para ao Dropbox e fazer algumas operações basicas, listar arquivos, upload e download, para isso usei o &lt;a href="https://github.com/dropbox/dropbox-sdk-go-unofficial">dropbox-sdk-go-unofficial&lt;/a>.&lt;/p>
&lt;h2 id="conectando-dropbox">Conectando Dropbox&lt;/h2>
&lt;p>Para conectar o dropbox precisamos das credenciais de acesso, a forma mais fácil é criar um token, para isso entre em &lt;a href="https://www.dropbox.com/developers/apps">Dropbox developers apps&lt;/a> e crie uma aplicação, então dentro do painel da aplicação crie o token.&lt;/p>
&lt;h2 id="configurando-o-sistema">Configurando o sistema&lt;/h2>
&lt;p>Todas as funções precisam das configurações com as credenciais de acesso e outros parâmetros úteis como por exemplo o nível de log. Então criamos uma função para retornar uma instancia da struct config.&lt;/p></description></item><item><title>Editar linhas de comando no terminal</title><link>https://crg.eti.br/pt-br/pub/comandos-longos-no-terminal/</link><pubDate>Sun, 08 Jul 2018 06:45:14 +0000</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/comandos-longos-no-terminal/</guid><description>&lt;p>Eu uso muito o terminal, é incrível como a boa e velha &lt;em>interface de linha de comando&lt;/em> &lt;code>cli&lt;/code> continua relevante e simplesmente a forma mais rápida de comandar um computador apesar de tantos anos de evolução da informática.&lt;/p>
&lt;p>Simplesmente ainda não descobrimos uma forma melhor de entrar comandos mas com o passar do tempo esses comandos foram crescendo e se tornando praticamente pequenos programas, as vezes com algumas linhas de código e até coisas difíceis de editar como expressões regulares por exemplo.&lt;/p></description></item><item><title>Compilação Estática Com Golang</title><link>https://crg.eti.br/pt-br/pub/compilacao-estatica-com-golang/</link><pubDate>Sat, 02 Dec 2017 16:57:41 -0200</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/compilacao-estatica-com-golang/</guid><description>&lt;h2 id="criando-executáveis-monolíticos">Criando executáveis monolíticos&lt;/h2>
&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=kdPWsCTREY8">aqui&lt;/a>.&lt;/p>
&lt;p>Golang já faz um bom trabalho compilando estaticamente praticamente tudo, mas dependendo do seu código é necessário incluir mais alguns parâmetros para garantir que seu executável seja totalmente livre de dependências.&lt;/p>
&lt;p>A primeira coisa é compilar o seu projeto e então inspecionar o binário para ver se ele tem alguma dependência.&lt;/p>
&lt;p>Para fazer isso no macOS usamos o utilitário &lt;code>otool&lt;/code> (object file displaying tool) passando o parâmetro &lt;code>-L&lt;/code> (mostra as &lt;em>shared libraries&lt;/em> usadas) como no exemplo:&lt;/p></description></item><item><title>Acessando a porta serial</title><link>https://crg.eti.br/pt-br/pub/formas-que-uso-para-acessar-porta-serial/</link><pubDate>Sat, 30 Sep 2017 21:22:29 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/formas-que-uso-para-acessar-porta-serial/</guid><description>&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=4_TqPdyEQVM">aqui&lt;/a>.&lt;/p>
&lt;p>E para mim uma das coisas mais interessantes é que os desenvolvedores preferiram deixar de fora algumas coisas que tem no screen, como o suporte a telnet e a portas seriais, eles fizeram isso porque acreditam na filosofia &lt;a href="https://en.wikipedia.org/wiki/Unix">UNIX&lt;/a> de faça apenas uma coisa e faça bem feito. E na minha opinião eles estão muito certos.&lt;/p>
&lt;h2 id="vamos-ver-algumas-formas-de-acessar-a-serial">Vamos ver algumas formas de acessar a serial&lt;/h2>
&lt;p>A única coisa que você tem que se lembrar não importa o modo que escolha para abrir a porta serial é que ela é feira para ser acessada apenas por um programa por vez, e para que outro programa consiga usar a mesma porta é necessário que o primeiro programa feche ela. Isso acontece muito por exemplo quando se esquece uma sessão do terminal serial do &lt;a href="https://www.arduino.cc">Arduino&lt;/a> aberto.&lt;/p></description></item><item><title>Um conto de terror para programadores</title><link>https://crg.eti.br/pt-br/pub/um-conto-de-terror-para-programadores/</link><pubDate>Wed, 26 Jul 2017 10:56:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/um-conto-de-terror-para-programadores/</guid><description>&lt;p>Já tem muitos anos havia uma &lt;a href="https://en.wikipedia.org/wiki/Electronic_mailing_list">lista de discussão&lt;/a> sobre Linux bem famosa, todo mundo se reunia por lá. Mas estávamos no início e as coisas não eram nem de perto tão robustas como são hoje, listas de e-mails ainda eram o principal meio para trocar informações porque ninguém tinha uma conexão 7x24 como as que temos hoje, você conectava, baixava seus e-mails, lia tudo off-line, respondia, conectava novamente e enviava suas respostas. Tudo muito rústico, mas funcionava.&lt;/p></description></item><item><title>Golang brincando com bits</title><link>https://crg.eti.br/pt-br/pub/go-brincando-com-bits/</link><pubDate>Mon, 03 Apr 2017 18:39:50 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-brincando-com-bits/</guid><description>&lt;h2 id="brincando-com-bits">Brincando com bits&lt;/h2>
&lt;p>A ideia é manipular a paleta de cores do CGA que armazena as cores em um unico byte, essa brincadeira parece complicada mas na verdade é muito simples, precisamos apenas aprender algumas poucas operações para poder manipular bits.&lt;/p>
&lt;p>Antes de começarmos vamos combinar o seguinte, quando eu falar sobre a parte superior ou alta de um conjunto de bits estou me referindo aos bits mais a esquerda, e quando estiver falando da parte inferior ou parte baixa estou falando dos bits mais a direita. Nem sempre é assim, mas para efeito desse texto é assim que funciona é o que chamamos de &lt;a href="https://en.wikipedia.org/wiki/Endianness">lite-endian&lt;/a>&lt;/p></description></item><item><title>Dicas de Golang defer</title><link>https://crg.eti.br/pt-br/pub/dicas-de-go-defer/</link><pubDate>Fri, 24 Mar 2017 20:12:16 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/dicas-de-go-defer/</guid><description>&lt;p>Usar &lt;a href="https://blog.golang.org/defer-panic-and-recover">defer&lt;/a> para adiar um comando até a função terminar, independentemente de como ela termine, é uma excelente ideia. Imagine uma função com vários pontos de retorno, seja para erros ou para terminar corretamente. Gerenciar o fechamento de arquivos, conexões, mutexes e outros recursos em cada retorno torna-se entediante e inseguro. Você pode esquecer de fechar um recurso em algum retorno, e isso pode causar problemas sérios.&lt;/p>
&lt;p>Contudo, o uso de &lt;code>defer&lt;/code> tem um custo. O sistema empilha o comando adiado, e adiá-lo com &lt;code>defer&lt;/code> é alguns nanossegundos mais lento do que uma chamada direta. Isso geralmente não é um problema no dia a dia, mas se você precisa maximizar a performance do seu código, pode ser algo a considerar.&lt;/p></description></item><item><title>Golang previnindo data race</title><link>https://crg.eti.br/pt-br/pub/go-previnindo-data-race/</link><pubDate>Sat, 11 Mar 2017 18:11:14 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-previnindo-data-race/</guid><description>&lt;p>No projeto do &lt;a href="https://crg.eti.br/pt-br/pub/go-carregando-arquivos-sped-fiscal-super-rapido/">Ricardo Gomes onde ganhamos uma bela performace&lt;/a> também acabamos acidentalmente incluindo uma bela data race.&lt;/p>
&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=BpCtTkJKDxU">aqui&lt;/a>.&lt;/p>
&lt;p>Data race acontece quando você tem acessos simultâneos a mesma variável por duas threads diferentes.&lt;/p>
&lt;p>Mas Golang tem ferramentas para tudo, e nessa brincadeira eu aprendi sobre o parâmetro &lt;a href="https://golang.org/doc/articles/race_detector.html">-race&lt;/a>. Esse parâmetro faz com que o Golang procure por possíveis data races em seu código e pode ser usado com test, run, build e install.&lt;/p></description></item><item><title>Golang carregando arquivos Sped Fiscal 95% mais rápido</title><link>https://crg.eti.br/pt-br/pub/go-carregando-arquivos-sped-fiscal-super-rapido/</link><pubDate>Mon, 06 Mar 2017 20:52:00 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-carregando-arquivos-sped-fiscal-super-rapido/</guid><description>&lt;p>No ultimo domingo eu e o Ricardo Gomes da Fix Auditoria fizemos pair programming com a missão de melhorar o &lt;a href="https://github.com/chapzin/parse-efd-fiscal">parse de EFD Fiscal&lt;/a> que ele esta desenvolvendo em Golang.&lt;/p>
&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=gnTsHQEVoZE">aqui&lt;/a>.&lt;/p>
&lt;p>O nosso objetivo era fazer o parser ganhar alguma performace e também resolver alguns pequenos problemas na carga dos arquivos.&lt;/p>
&lt;p>O que o sistema faz até o momento é o seguinte: Le vários arquivos texto contendo centenas de milhares de registros, parseia esse conteúdo linha a linha e por fim grava tudo no banco de dados.&lt;/p></description></item><item><title>Assembly 16Bits no macOS com NASM e DOSBox</title><link>https://crg.eti.br/pt-br/pub/assembly-16bits-nasm-dosbox/</link><pubDate>Sat, 04 Mar 2017 18:16:31 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/assembly-16bits-nasm-dosbox/</guid><description>&lt;h2 id="brincando-com-assembly">Brincando com Assembly&lt;/h2>
&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=Q1jNzLugyz8">aqui&lt;/a>.&lt;/p>
&lt;p>Brincar com assembly é divertido, só com asm você tem controle total da maquina e de cada aspecto do seu programa, não há nada escondido e o computador vai fazer exatamente o que você mandou (não necessariamente o que você quer).&lt;/p>
&lt;p>Hoje me dia assembly para mim é um hobby, não estou mexendo com nada tão baixo nível que realmente precise descer até o asm mas como diversão NERD não tem igual e recentemente encontrei meus antigos guias de referencia rápida das interrupções da &lt;a href="https://en.wikipedia.org/wiki/BIOS">BIOS&lt;/a> e do &lt;a href="https://en.wikipedia.org/wiki/MS-DOS">MS-DOS&lt;/a>.&lt;/p></description></item><item><title>Golang percorrendo a árvore de diretórios</title><link>https://crg.eti.br/pt-br/pub/go-percorrendo-diretorios-com-filepath-walk/</link><pubDate>Tue, 28 Feb 2017 09:07:51 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-percorrendo-diretorios-com-filepath-walk/</guid><description>&lt;p>Eu enfrentava o problema de ter que digitar o caminho completo para acessar o diretório do projeto no qual queria trabalhar. Tudo está no GOPATH e os caminhos geralmente são longos. Embora digitar o caminho completo de vez em quando seja aceitável, trabalho diariamente com &lt;a href="https://golang.org">golang&lt;/a> em vários projetos. Ter que digitar o caminho completo constantemente se torna entediante. Às vezes, eu nem sei exatamente onde o projeto está ou esqueço partes do caminho, como o nome do autor ou se está no &lt;a href="https://github.com/crgimenes">GitHub&lt;/a> ou em outro repositório.&lt;/p></description></item><item><title>go usando time e canais</title><link>https://crg.eti.br/pt-br/pub/go-usando-time-e-canais/</link><pubDate>Sun, 05 Feb 2017 19:19:29 -0200</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-usando-time-e-canais/</guid><description>&lt;h2 id="pacote-time">Pacote time&lt;/h2>
&lt;p>Eu sou o primeiro a torcer o nariz para o pacote time, principalmente pela maneira como a formatação de datas é feita, mas um recurso muito interessante é poder criar um canal que retorna a cada X tempo e assim podemos executar ações periódicas.&lt;/p>
&lt;p>Veja o vídeo desse arquivo &lt;a href="https://www.youtube.com/watch?v=jTBtVrn-Cq8">aqui&lt;/a>.&lt;/p>
&lt;h2 id="veja-como-isso-é-feito">Veja como isso é feito&lt;/h2>
&lt;p>Primeiro criamos um canal que vai retornar a cada X tempo, no caso do exemplo 300 milissegundos.&lt;/p></description></item><item><title>Golang plugins</title><link>https://crg.eti.br/pt-br/pub/go-plugins/</link><pubDate>Sun, 05 Feb 2017 11:19:27 -0200</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-plugins/</guid><description>&lt;p>Plugins são um dos poucos recursos quase esquecidos do Go e, francamente, eu desaconselho seu uso. Ao contrário de outros recursos da linguagem, plugins funcionam apenas no Linux, BSD e macOS. Como são baseados no &lt;code>dlopen&lt;/code>, você não pode descarregar nem substituir um plugin depois de carregá-lo. Além disso, é necessário usar CGO, o que pode trazer mais complicações.&lt;/p>
&lt;p>Apesar dos problemas, plugins são recursos interessantes e podem ser úteis em alguns casos, como carregar um módulo de forma dinâmica.&lt;/p></description></item><item><title>GitHub a rede social do programador</title><link>https://crg.eti.br/pt-br/pub/github-rede-social-do-programador/</link><pubDate>Sat, 24 Dec 2016 14:25:19 -0200</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/github-rede-social-do-programador/</guid><description>&lt;p>&lt;strong>Talk is cheap. Show me the code.&lt;/strong>
&lt;em>- Linus Torvalds em uma mensagem para a linux-kernel mailing list em 25/08/2000&lt;/em>&lt;/p>
&lt;h2 id="lone-gunman">Lone Gunman&lt;/h2>
&lt;p>Durante a maior parte da minha carreira eu trabalhei sozinho ou em equipes muito pequenas, é fácil manter controle de versão quando se esta sozinho, qualquer sistema vai funcionar desde que ele não entre na sua frente e seja minimamente eficiente, eu programo desde os anos 90 e já passei por tudo, desde copiar todo o projeto para um outro diretório, ou zipar o projeto com a data da mudança, CVS, SVN, e agora Git. De todos esses o Git é sem duvida o melhor equilíbrio entre funcionalidade e praticidade, a curva de aprendizado é bastante suave com quatro ou cinco comandos você esta usando Git sem problemas. E hoje os tempos de pistoleiro solitário ficaram para traz, trabalho em uma equipe e não estamos juntos na mesma sala, trabalhamos de forma assíncrona e o controle de versão precisa absorver isso. A natureza descentralizada do Git ajuda muito a juntar varias partes do trabalho e montar o quebra-cabeça que é um software moderno.&lt;/p></description></item><item><title>Assembly, assembler e linguagem de maquina</title><link>https://crg.eti.br/pt-br/pub/assembly-assembler-e-linguagem-de-maquina/</link><pubDate>Sun, 11 Sep 2016 08:16:28 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/assembly-assembler-e-linguagem-de-maquina/</guid><description>&lt;h2 id="são-coisas-diferentes">São Coisas Diferentes&lt;/h2>
&lt;p>Existem três conceitos diferentes, mas relacionados, que as pessoas frequentemente confundem. Vamos esclarecer cada um deles.&lt;/p>
&lt;h3 id="assembly">Assembly&lt;/h3>
&lt;p>Assembly é uma linguagem de programação composta por mnemônicos simples. Ela corresponde diretamente às instruções da plataforma utilizada. Ao escrever código em Assembly, você sabe exatamente o que o processador está fazendo e tem acesso a recursos que podem não estar disponíveis em linguagens de alto nível. Podemos chamar Assembly de uma linguagem de baixo nível, o que significa que está mais próxima do hardware.&lt;/p></description></item><item><title>Zero Configuration Networking</title><link>https://crg.eti.br/pt-br/pub/zero-configuration-network-no-debian/</link><pubDate>Sun, 04 Sep 2016 11:11:33 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/zero-configuration-network-no-debian/</guid><description>&lt;p>Frequentemente adiciono novos dispositivos à minha rede para diferentes finalidades. Esses dispositivos podem ser qualquer coisa: um &lt;a href="https://en.wikipedia.org/wiki/Single-board_computer">SBC&lt;/a> para projetos de IoT, uma máquina virtual para testar software sem afetar os sistemas principais ou uma VM descartável para testes rápidos.&lt;/p>
&lt;p>Isso gera um problema: como descobrir o IP para acessar esses recursos? Poderia verificar o DHCP, atribuir IPs fixos ou outras soluções, mas todas são pouco práticas. Preciso de uma solução fácil e rápida que funcione para mim e para scripts que precisam localizar recursos na rede, mesmo que o IP tenha mudado.&lt;/p></description></item><item><title>Tratando sinais com Go</title><link>https://crg.eti.br/pt-br/pub/tratando-sinais-com-go/</link><pubDate>Mon, 18 Jul 2016 16:36:22 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/tratando-sinais-com-go/</guid><description>&lt;p>Tratar sinais é uma boa prática. Dessa forma, você pode finalizar seu programa graciosamente, liberando recursos e fechando bancos de dados, em vez de simplesmente encerrar o programa. Tratar sinais do sistema operacional com Golang é simples, pois o sistema envia o sinal para um canal. Basta escutar esse canal.&lt;/p>
&lt;p>Primeiro, criamos um canal:&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-golang" data-lang="golang">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#1f2328">sc&lt;/span> &lt;span style="color:#0550ae">:=&lt;/span> &lt;span style="color:#6639ba">make&lt;/span>&lt;span style="color:#1f2328">(&lt;/span>&lt;span style="color:#cf222e">chan&lt;/span> &lt;span style="color:#1f2328">os&lt;/span>&lt;span style="color:#1f2328">.&lt;/span>&lt;span style="color:#1f2328">Signal&lt;/span>&lt;span style="color:#1f2328">,&lt;/span> &lt;span style="color:#0550ae">1&lt;/span>&lt;span style="color:#1f2328">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Em seguida, informamos o tipo de sinal que nos interessa. No caso, ^C, ou seja, &lt;a href="https://en.wikipedia.org/wiki/Unix_signal#SIGINT">SIGINT&lt;/a>.&lt;/p></description></item><item><title>Usando diff e patch</title><link>https://crg.eti.br/pt-br/pub/usando-diff-e-patch/</link><pubDate>Fri, 15 Jul 2016 23:30:17 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/usando-diff-e-patch/</guid><description>&lt;p>Esses dois comandos são ferramentas extremamente úteis para o programador, com esses dois comandos fica fácil enviar patchs (&lt;em>remendos&lt;/em>) de código para outros programadores sem precisar enviar o código todo.&lt;/p>
&lt;h2 id="diff">diff&lt;/h2>
&lt;p>Digamos que você tem dois arquivos texto, um original e outro que é uma cópia do original com alguma modificação.&lt;/p>
&lt;p>O comando diff procura por diferenças entre dois arquivos ou mesmo duas arvores de diretórios, a forma mais simples de usar esse comando é a seguinte:&lt;/p></description></item><item><title>HTTPS com Golang no Linux</title><link>https://crg.eti.br/pt-br/pub/https-com-golang/</link><pubDate>Thu, 30 Jun 2016 09:37:25 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/https-com-golang/</guid><description>&lt;h2 id="gerando-as-chaves-com-letsencryptorg">Gerando as chaves com letsencrypt.org&lt;/h2>
&lt;p>Como eu mencionei no post sobre &lt;a href="https://crg.eti.br/pt-br/pub/redirect-to-https/">redirecionar tudo para HTTPS&lt;/a> todas as comunicações entre cliente e servidor precisam ser criptografadas e com &lt;a href="https://letsencrypt.org">letsencrypt.org&lt;/a> isso pode ser feito sem custo, com código aberto e muita documentação, o que no meu ponto de vista acaba com todas as desculpas para não usar HTTPS.&lt;/p>
&lt;p>Uma ressalva importante é que podem haver razões legais para preferir usar outra entidade certificadora, por exemplo se eu não estou enganado para ter valor legal no Brasil a entidade precisa ser brasileira. Claro que isso só importa se você estiver querendo processar alguém, eu estou interessado apenas na segurança.&lt;/p></description></item><item><title>Redirect para HTTPS e proxy reverso</title><link>https://crg.eti.br/pt-br/pub/redirect-to-https/</link><pubDate>Tue, 28 Jun 2016 11:22:10 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/redirect-to-https/</guid><description>&lt;h2 id="tudo-criptografado-sem-desculpas">Tudo criptografado, Sem desculpas&lt;/h2>
&lt;p>Antigamente era caro e inconveniente exigir criptografia para servidores HTTP, você teria que no mínimo gastar alguns trocados com uma entidade certificadora. De um tempo para cá isso não é mais verdade, qualquer um pode usar os certificados da &lt;a href="https://letsencrypt.org">letsencrypt.org&lt;/a>, é free, fácil de usar e as ferramentas são de código aberto, então não existe mais desculpa para não usar HTTPS nos seus servidores.&lt;/p>
&lt;p>Além de poder usar os certificados diretamente várias ferramentas e serviços estão atualmente gerando o certificado do Let&amp;rsquo;s Encrypt para você, é o caso do &lt;a href="https://caddyserver.com">Caddy&lt;/a> que basta você fornecer um nome de domínio no seu arquivo de configuração e ele vai solicitar o certificado e usar tudo de forma transparente.&lt;/p></description></item><item><title>String aleatória segura em Golang usando crypto/rand</title><link>https://crg.eti.br/pt-br/pub/go-strings-aleatorias/</link><pubDate>Wed, 13 Apr 2016 11:30:39 -0300</pubDate><author>crg@crg.eti.br (Cesar Gimenes)</author><guid>https://crg.eti.br/pt-br/pub/go-strings-aleatorias/</guid><description>&lt;p>Gerar strings aleatórias é extremamente útil. Esse recurso é usado em muitos lugares, como criar chaves para registros em bancos de dados distribuídos sem risco de colisão entre registros, criar IDs de controle de sessão, gerar senhas e muito mais.&lt;/p>
&lt;p>Apesar de ser uma tarefa simples, há alguns truques interessantes. Na verdade, computadores não são bons para criar coisas verdadeiramente aleatórias. Eles criam coisas previsíveis, o que não é desejável quando o objetivo é criptografia e segurança.&lt;/p></description></item></channel></rss>