<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Development on Cesar Gimenes</title><link>https://crg.eti.br/tags/development/</link><description>Recent content in Development on Cesar Gimenes</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>crg@crg.eti.br (Cesar Gimenes)</managingEditor><webMaster>crg@crg.eti.br (Cesar Gimenes)</webMaster><lastBuildDate>Sun, 16 Aug 2026 10:30:00 -0300</lastBuildDate><atom:link href="https://crg.eti.br/tags/development/index.xml" rel="self" type="application/rss+xml"/><item><title>Kutta in the Browser: Same Code, a Different Frame Budget</title><link>https://crg.eti.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/pub/kutta-no-navegador/</guid><description>&lt;p>&lt;a href="https://crg.eti.br/en/pub/kutta/">Kutta&lt;/a> now runs inside a browser tab. Same source as the desktop build, &lt;code>GOOS=js GOARCH=wasm&lt;/code>, no fork, no duplicated file holding a &amp;ldquo;web&amp;rdquo; version of the 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 shedding vortices at 20 degrees angle of attack" 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>Speed is what you pay. A solver step costs &lt;strong>6.1 ms under wasm against 2.3 ms native&lt;/strong>, measured on the 360x200 grid the app runs, on an M4 Mac, same solver compiled for both targets on the same machine. Factor of 2.6.&lt;/p></description></item><item><title>Kutta, a Tiny Wind Tunnel in Go</title><link>https://crg.eti.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/pub/kutta/</guid><description>&lt;p>You can explain lift with a diagram and an equation. It rarely sticks. Watch a wake peel off the back of a wing while you turn the angle of attack, and it sticks immediately. That gap is the whole reason &lt;strong>Kutta&lt;/strong> exists.&lt;/p>
&lt;p>It is a small 2D wind tunnel written in Go, rendered with &lt;a href="https://ebitengine.org">Ebitengine&lt;/a>, running as a single desktop app.&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 running" src="https://crg.eti.br/pub/kutta/kutta.webp" height="338" width="600" loading="lazy" decoding="async">&lt;/a>
&lt;/figure>
&lt;p>The idea never grew past the first sketch: stream air past an airfoil and make the flow visible. Change the angle of attack and the field reacts. Toggle between speed, vorticity and a pressure-like field. Draw your own shape. Cut a wing into a wing and a flap, animate the flap, and watch the wake go unstable when the geometry or the angle gets greedy.&lt;/p></description></item><item><title>Glaze, a Desktop WebView in Go Without CGO</title><link>https://crg.eti.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/pub/glaze/</guid><description>&lt;p>Opening a window with HTML in Go almost always charges a toll in C.&lt;/p>
&lt;p>Either you turn on cgo and drag a C toolchain into the project, or someone embeds a compiled &lt;code>.dll&lt;/code>/&lt;code>.so&lt;/code>/&lt;code>.dylib&lt;/code> in the binary and extracts it to disk on first run. Both work. And both take away exactly what I like about the ecosystem: the &lt;code>go build&lt;/code> that cross-compiles to three systems without a second thought, the reproducible build, the &lt;code>go install&lt;/code> that works for anyone who cloned the repo. It&amp;rsquo;s the first thing that goes the moment C enters the picture.&lt;/p></description></item><item><title>Neko, a cat chasing the mouse with Go and Ebitengine</title><link>https://crg.eti.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/pub/neko/</guid><description>&lt;p>Every programmer should write at least one useless piece of software on purpose.&lt;/p>
&lt;p>Useless here in the best sense. It serves no business, will never show up in a product meeting, and stands no chance of some manager asking for webhook integration. Even so, it forces you to deal with real problems. Screen, input, timing, sprites, sound, window, operating system. A toy like that teaches more about interactive software than a pile of CRUD apps dressed up as corporate demos.&lt;/p></description></item><item><title>LQS: A Practical Tool for Testing and Debugging SQL</title><link>https://crg.eti.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/pub/lqs-uma-ferramenta-prtica-para-testar-sql/</guid><description>&lt;p>It&amp;rsquo;s very common to need to embed SQL code strings in the source of other languages. The problem is that SQL is an interpreted language, so it can contain errors that we only notice at runtime.&lt;/p>
&lt;h2 id="testing-sql">Testing SQL&lt;/h2>
&lt;p>LQS was created to work together with Neovim and allow you to test SQL while editing, without having to copy and paste into another file or SQL client.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Test SQL with embedded metadata:&lt;/strong>
Insert configurations directly in your SQL script, such as the connection string, JSON output option, or even an extra query to generate parameters.
Example:&lt;/p></description></item><item><title>Sorting and Removing Duplicate Lines with Neovim</title><link>https://crg.eti.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/pub/nvim-sort/</guid><description>&lt;p>Good organization makes code easier to read. Disorganized lists make it difficult to maintain a project, and they also give your code an unprofessional look.&lt;/p>
&lt;p>These two functions sort and remove duplicate lines in selected text blocks in &lt;em>Neovim&lt;/em>.&lt;/p>
&lt;p>The &lt;code>sort_lines&lt;/code> function sorts the selected lines:&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>The &lt;code>sort_and_uniq_lines&lt;/code> function sorts and removes duplicate lines:&lt;/p></description></item><item><title>Bookmarks in Neovim</title><link>https://crg.eti.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/pub/nvim-bookmarks/</guid><description>&lt;p>I go through many files when I work, especially when debugging or tracing behaviors. I created a bookmark system in &lt;em>Neovim&lt;/em> to quickly jump between files. This system differs from the default &lt;em>Neovim&lt;/em> system because it focuses on marking files and lines, not just positions within the same file.&lt;/p>
&lt;h2 id="how-it-works">How It Works&lt;/h2>
&lt;p>The system records the file path and the current line in a text file. I use the &lt;code>&amp;lt;leader&amp;gt;o&lt;/code> key to open all marked files. I use the &lt;code>&amp;lt;leader&amp;gt;m&lt;/code> key to mark a file. I also use the &lt;code>:Clearmarks&lt;/code> command to clear all bookmarks when I finish a task or start a new one.&lt;/p></description></item><item><title>GoScope: Exploring and Navigating Go Projects</title><link>https://crg.eti.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/pub/goscope-explorando-e-navegando-em-projetos-go/</guid><description>&lt;p>I often want to quickly analyze a Go project to understand where functions, variables, and types are defined or called. That&amp;rsquo;s why I created two command-line tools: &lt;strong>GoScope&lt;/strong> and &lt;strong>rgs&lt;/strong>. The first scans every &lt;code>.go&lt;/code> file in a project, producing a list of definitions and function calls. The second uses that list to let me navigate interactively to the exact spot in the code.&lt;/p>
&lt;h2 id="goscope">GoScope&lt;/h2>
&lt;p>&lt;a href="https://github.com/crgimenes/GoScope">&lt;strong>GoScope&lt;/strong>&lt;/a> walks through all &lt;code>.go&lt;/code> files recursively starting from the current directory. It prints:&lt;/p></description></item><item><title>Static Compilation of the Lua Interpreter: Consistency and Portability</title><link>https://crg.eti.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/pub/compilacao-estatica-da-lingagem-lua/</guid><description>&lt;p>Lua is my favorite language for writing small scripts and configurations. It is easy to embed in other projects and has a clean, simple syntax. It is easy to extend and a great language for configuring systems.&lt;/p>
&lt;p>I recently started a project that requires the Lua interpreter to be installed. That is usually not a problem. But to have full control, I decided to compile my own statically linked version of the interpreter. This ensures that differences in the libc version or other libraries won&amp;rsquo;t interfere with my system. I&amp;rsquo;ve run into plenty of problems with systems that failed to load because of mismatched glibc versions. Beyond the practical reasons, I believe all software should be statically compiled. The memory savings and easier updates of dynamic linking don&amp;rsquo;t make up for the problems it can cause.&lt;/p></description></item><item><title>Safe JSON Validation and Integration in Go APIs with json.RawMessage</title><link>https://crg.eti.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/pub/validacao-e-integracao-segura-de-json-em-apis-go/</guid><description>&lt;p>I recently built an API where the user sends a JSON value in one of the fields. The requirement was to log invalid JSON errors but let the rest of the data continue through the system&amp;rsquo;s normal flow.&lt;/p>
&lt;p>It was also important that, if the received JSON was valid, it would be integrated seamlessly into the API responses. Since the JSON could vary and I didn&amp;rsquo;t know its structure, I used &lt;code>json.RawMessage&lt;/code> as the field type. That way, when calling &lt;code>json.Marshal&lt;/code>, the data is correctly embedded into the main JSON.&lt;/p></description></item><item><title>Benchmark: Named vs Explicit Returns in Go</title><link>https://crg.eti.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/pub/benchmark-retornos-nomeados-vs-explicitos-go/</guid><description>&lt;p>A question came up in our Go study group: are named returns faster than explicit returns? That was the hypothesis.&lt;/p>
&lt;p>Fortunately, Go has good tools to test this.&lt;/p>
&lt;p>Let&amp;rsquo;s write some code with two sum functions: one with named returns and one with explicit returns.&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>Next, we create the benchmark functions. The names of these functions matter. Go&amp;rsquo;s testing tool looks for functions that start with &amp;ldquo;Benchmark&amp;rdquo;.&lt;/p></description></item><item><title>Programming as Art</title><link>https://crg.eti.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/pub/arte-generativa-em-javascript-segunda-parte/</guid><description>&lt;p>I consider programming computers a form of artistic expression. There are many ways to solve everyday programming problems, which leaves plenty of room for creativity.&lt;/p>
&lt;p>&lt;canvas id="grid_rect_canvas" class="genart_full">&lt;/canvas>&lt;/p>
&lt;h2 id="classic-examples-of-generative-art">Classic Examples of Generative Art&lt;/h2>
&lt;p>And there are many interesting examples of computer-generated art. My favorites are the &amp;ldquo;one-liners&amp;rdquo;, programs of just a single line that do interesting things, like the famous &lt;code>10 PRINT CHR$ (205.5 + RND (1)); : GOTO 10&lt;/code> that draws a maze using &lt;em>BASIC&lt;/em>, and the more modern equivalent &lt;code>yes 'c=(╱ ╲);printf ${c[RANDOM%2]}'|bash&lt;/code> written in &lt;em>Bash&lt;/em>. A quick search on the internet will turn up several implementations in different languages.&lt;/p></description></item><item><title>Generative Art in JavaScript for the Sides of the Site</title><link>https://crg.eti.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/pub/arte-generativa-em-javascript/</guid><description>&lt;p>After a long time, I finally added some JavaScript to this site.&lt;/p>
&lt;p>I have a huge mental block when it comes to web technologies. JavaScript, CSS, and even HTML itself feel very improvised to me, especially the whole idea of the &amp;ldquo;single page application&amp;rdquo;.&lt;/p>
&lt;p>This is a limitation I need to get over. After all, these days the web really is the best and most portable interface for most programs, even though it goes against a lot of what I believe about minimalism and saving resources.&lt;/p></description></item><item><title>Post-Apocalyptic Computing</title><link>https://crg.eti.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/pub/computacao-pos-apocaliptica/</guid><description>&lt;p>Post-apocalyptic computing is a game, an interesting exercise for your imagination. The scenario goes like this: something terrible has happened and the society you live in no longer exists. As a survivor, it&amp;rsquo;s up to you to help rebuild modern society.&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="Post-apocalyptic computing" 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>The cause of the apocalypse can be whatever you like: nuclear war, plague, economic collapse, a solar storm, an oppressive government that wants to keep technology to itself, and so on. The only constant is that nothing you take for granted is available. All the infrastructure is gone. There&amp;rsquo;s no more running water, no electricity, none of the amenities of modern life.&lt;/p></description></item><item><title>Deploying Applications Using curl</title><link>https://crg.eti.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/pub/deploy_de_aplicacoes_usando_curl/</guid><description>&lt;p>Small teams face several challenges when distributing binaries these days. If you simply put an application up for download on a website, search tools will immediately flag your site as suspicious content. Browsers show the user a scary warning, and there is no way to remove it, even with a signed binary. The warning only goes away once enough users have downloaded your binary without reporting problems.&lt;/p>
&lt;p>Letting the user download the binary from some already well-known site, even GitHub, isn&amp;rsquo;t ideal, especially for closed-source applications.&lt;/p></description></item><item><title>Studying Assembly</title><link>https://crg.eti.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/pub/estudando-assembly/</guid><description>&lt;p>When I started programming, back in the 8-bit era, learning a bit of assembly was unavoidable. The machines were far simpler than today&amp;rsquo;s computers, and we often didn&amp;rsquo;t even have a compiler at hand. Instead, we typed small chunks of opcodes directly in hexadecimal.&lt;/p>
&lt;p>This was incredibly useful for working around the limitations of the BASIC that served both as a programming language and as the operating system (burned straight into the machine&amp;rsquo;s ROM).&lt;/p></description></item><item><title>Hidden Files on UNIX</title><link>https://crg.eti.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/pub/arquivos-ocultos-no-unix/</guid><description>&lt;p>Everyone knows how to create hidden files in the UNIX/Linux world: just start the file name with a dot (.). But this feature wasn&amp;rsquo;t always there.&lt;/p>
&lt;p>According to Rob Pike in a Google+ post that is now only available on archive.org, around version 2 of UNIX, while the Unix file system design was being worked on, the &amp;ldquo;.&amp;rdquo; and &amp;ldquo;..&amp;rdquo; entries appeared to make directory navigation easier. This probably happened in version 2, when the file system became hierarchical.&lt;/p></description></item><item><title>Socket Client and Server in Golang: A Chat Example</title><link>https://crg.eti.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/pub/golang-cliente-servidor-socket-chat/</guid><description>&lt;p>This is the fourth version of our socket client and server. In this version, I made some interesting improvements. We now have a complete chat system with useful commands and a few optimizations.&lt;/p>
&lt;p>The goal of this version is to refine the system. I removed one of the write channels to send data directly, increasing efficiency. I also dropped the automatic reconnection to keep the code cleaner, since I added several new features.&lt;/p></description></item><item><title>Assembly on macOS M1/ARM64.</title><link>https://crg.eti.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/pub/assembly-m1/</guid><description>&lt;p>Here is the story. I had found a great deal on two early-90s computers still running &lt;a href="https://en.wikipedia.org/wiki/Zilog_Z80">Zilog Z80&lt;/a> processors. They weren&amp;rsquo;t in perfect shape, but the price was fine.&lt;/p>
&lt;p>Then a good friend, with far more common sense than me, advised me to stop wasting energy and money on old hardware. To cool down this nerd fever, he suggested I study ARM assembly instead, since it could at least be useful.&lt;/p></description></item><item><title>Socket client and server in Golang with signal handling.</title><link>https://crg.eti.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/pub/golang-cliente-servidor-socket-signals/</guid><description>&lt;p>Continuing our series of articles about client/server, we will add a new channel to the &lt;a href="../golang-cliente-servidor-socket-ping-pong">previous example&lt;/a>. This channel will handle signals sent by the operating system.&lt;/p>
&lt;p>The operating system sends signals to programs to manage processes. For example, when you press &lt;em>Ctrl+C&lt;/em>, the operating system sends the SIGINT signal, telling the program that the user wants to interrupt it.&lt;/p>
&lt;p>By default, the program is closed. However, we can intercept this signal and act accordingly. In this case, we will simply terminate the program. In real systems, this feature can be used to save information before closing, stop other processes, close connections and files, and so on. This process is known as &lt;em>graceful shutdown&lt;/em>.&lt;/p></description></item><item><title>Socket Client and Server in Golang with Ping and Pong.</title><link>https://crg.eti.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/pub/golang-cliente-servidor-socket-ping-pong/</guid><description>&lt;p>Continuing the &lt;a href="../golang-cliente-servidor-socket-com-canais-e-goroutines">conversation about a resilient client and server&lt;/a>, it&amp;rsquo;s time to improve the server and add the sending of &lt;em>ping&lt;/em> or &lt;em>keep alive&lt;/em> messages.&lt;/p>
&lt;p>We also made improvements to the server. Now, just like the client, it uses goroutines and channels.&lt;/p>
&lt;h2 id="server">Server&lt;/h2>
&lt;h3 id="reading-from-the-connection">Reading from the Connection&lt;/h3>
&lt;p>In this version, the server uses one goroutine to write and another to read the data from the client connection. When using goroutines and channels this way, it&amp;rsquo;s essential to make sure the goroutines are properly terminated.&lt;/p></description></item><item><title>Socket client and server in Golang with goroutines and channels.</title><link>https://crg.eti.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/pub/golang-cliente-servidor-socket-com-canais-e-goroutines/</guid><description>&lt;p>Continuing the &lt;a href="../golang-cliente-servidor-socket">example about a persistent socket client in Golang&lt;/a>, I made a few changes to the source code to show how to improve our code and make it asynchronous. To do that, we&amp;rsquo;ll use goroutines and channels.&lt;/p>
&lt;h2 id="goroutines-and-channels">Goroutines and Channels&lt;/h2>
&lt;p>Goroutines and channels are advanced features of the Go language. Goroutines are lightweight threads managed by the language runtime itself, and channels allow communication between goroutines.&lt;/p>
&lt;p>In our case, we&amp;rsquo;ll use channels for communication between the goroutines in our program.&lt;/p></description></item><item><title>Socket Client and Server in Golang.</title><link>https://crg.eti.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/pub/golang-cliente-servidor-socket/</guid><description>&lt;p>In the Go study group, a question came up about how to write a persistent client that reconnects to a socket server whenever the connection fails.&lt;/p>
&lt;p>The main difficulty people seem to have is understanding the concept of a state machine. So we&amp;rsquo;ll build a few examples of a persistent client, starting with a simple state machine, without goroutines or channels.&lt;/p>
&lt;p>Before that, we&amp;rsquo;ll create a small socket server for our client to connect to: the famous echo server.&lt;/p></description></item><item><title>Remote Clipboard</title><link>https://crg.eti.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/pub/area-de-transferencia-remota/</guid><description>&lt;p>&lt;em>Tip:&lt;/em> The &lt;code>pbcopy&lt;/code> command on the Mac is equivalent to &lt;code>xclip -selection clipboard&lt;/code> on Linux. The &lt;code>pbpaste&lt;/code> command on the Mac matches &lt;code>xclip -selection clipboard -o&lt;/code> on Linux. The &lt;code>xclip&lt;/code> command doesn&amp;rsquo;t work because it requires &lt;a href="https://en.wikipedia.org/wiki/X_Window_System">X Window&lt;/a> installed.&lt;/p>
&lt;h2 id="copy-and-paste">Copy and Paste&lt;/h2>
&lt;p>I edit a lot of code on remote servers over SSH, with no graphical interface, usually with &lt;a href="https://neovim.io">Neovim&lt;/a>. It would be great to copy and paste between the remote machine and the local one. Pasting from the local machine to the remote one is simple, since the terminal already handles it. Copying from the remote machine to the local one, however, takes a bit of code.&lt;/p></description></item><item><title>Speeding Up the Site</title><link>https://crg.eti.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/pub/acelerando-o-site/</guid><description>&lt;p>To share my articles over &lt;a href="https://ipfs.io">IPFS&lt;/a>, it made sense to embed the CSS and images directly into the HTML so that there would be a single file to share.&lt;/p>
&lt;p>Embedding the CSS was the simplest part: I just placed the CSS directly into the site template using the &lt;code>&amp;lt;style&amp;gt;&amp;lt;/style&amp;gt;&lt;/code> &lt;em>tag&lt;/em>, and embedding the CSS alone already produced a nice speed gain.&lt;/p>
&lt;p>I use &lt;a href="https://gohugo.io">HUGO&lt;/a> as the &lt;em>framework&lt;/em> to generate the site automatically. HUGO works by converting pages written in &lt;em>Markdown&lt;/em>, but the same idea applies no matter how the site is built, even if it is written by hand, directly in HTML. With HUGO and a bit of programming, though, it was easy to automate my template and have the images converted to &lt;em>Base64&lt;/em> and inserted into the page automatically.&lt;/p></description></item><item><title>How to Extend Git</title><link>https://crg.eti.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/pub/git-como-estender/</guid><description>&lt;p>Git is an extremely flexible tool and very simple to extend and build features on. To create a command, you just need an executable named git-&lt;strong>command&lt;/strong> (&lt;em>git dash followed by the command name&lt;/em>).&lt;/p>
&lt;p>Any executable on the PATH that follows this naming pattern will be called by git. To start with a simple example, let&amp;rsquo;s do the traditional &amp;ldquo;hello world&amp;rdquo;. Save the example below as &lt;code>git-hello&lt;/code> in a directory on the PATH.&lt;/p></description></item><item><title>Headless VirtualBox</title><link>https://crg.eti.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/pub/headless-virtualbox/</guid><description>&lt;p>&lt;strong>WIP - This text is a work in progress. I haven&amp;rsquo;t documented all the examples I wanted to yet, nor have I reviewed the text. Contributions are welcome.&lt;/strong>&lt;/p>
&lt;p>Continuing with the project of building a machine &lt;em>cluster&lt;/em>, I&amp;rsquo;m going to need some kind of virtualization system, because not all of the experiments I want to run can be done with containers alone. I did a few tests with &lt;a href="https://www.qemu.org">QEMU&lt;/a>, but for now it&amp;rsquo;s more practical to &lt;em>stick&lt;/em> with &lt;a href="https://www.virtualbox.org">VirtualBox&lt;/a>.&lt;/p></description></item><item><title>How to Shrink Your Container Using Multi-Stage Builds</title><link>https://crg.eti.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/pub/docker-multi-stage-build/</guid><description>&lt;p>Every now and then I run into some huge Docker image where 99% of the size is junk left behind while the image was being built. This is especially bad when we&amp;rsquo;re dealing with Go executables, which are self-contained and usually don&amp;rsquo;t need any external resources, not even libc.&lt;/p>
&lt;h2 id="multi-stage-builds">multi-stage builds&lt;/h2>
&lt;p>The solution is to use &lt;em>multi-stage builds&lt;/em>. This way you can have two stages in your Dockerfile: a build stage that downloads whatever is needed, compiles the code, and so on, and another that just copies the executables and resources to their expected locations. This second stage doesn&amp;rsquo;t even need to be based on a distribution; it can be a &lt;em>scratch&lt;/em> image, which shrinks the final size even further.&lt;/p></description></item><item><title>First steps when setting up a new server</title><link>https://crg.eti.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/pub/configurando-novo-servidor/</guid><description>&lt;p>Whenever I bring up a new machine I always run a few commands and set up some configuration. A lot of it is already handled by my &lt;a href="https://github.com/crgimenes/dotfiles">dotfiles&lt;/a>, but there&amp;rsquo;s always plenty of custom work left to do.&lt;/p>
&lt;p>The first thing is to get SSH access and make sure the root password isn&amp;rsquo;t the default one.&lt;/p>
&lt;p>Next I give my user sudo access, in case it doesn&amp;rsquo;t have it already.&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>usermod -aG sudo &lt;span style="color:#0a3069">${&lt;/span>&lt;span style="color:#953800">USER&lt;/span>&lt;span style="color:#0a3069">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If it&amp;rsquo;s a machine on the local network, I set it up to use &lt;a href="https://crg.eti.br/pub/zero-configuration-network-no-debian/">zero configuration network&lt;/a>, a much more convenient way to reach the machine, especially on IPv6 networks. Otherwise, this is a good time to add the machine to a domain.&lt;/p></description></item><item><title>Setting HTTP Request Timeouts in Golang</title><link>https://crg.eti.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/pub/go-http-timeout/</guid><description>&lt;p>By default, Go doesn&amp;rsquo;t set timeouts for HTTP requests, which can cause a number of problems and vulnerabilities. A DOS attack, for example, could simply open a large number of connections to your server.&lt;/p>
&lt;p>To fix this, create an instance of the &lt;code>http.Server&lt;/code> struct and fill in the &lt;code>WriteTimeout&lt;/code> and &lt;code>ReadTimeout&lt;/code> fields with values you consider appropriate.&lt;/p>
&lt;p>Here&amp;rsquo;s an example:&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>This sets the default timeout values for all HTTP requests.&lt;/p></description></item><item><title>Finding the IP with Golang</title><link>https://crg.eti.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/pub/descobrindo-ip-com-golang/</guid><description>&lt;p>I recently ran into an interesting problem: I needed to stand up a small REST service to manage some hardware, all without human intervention and with multiple network interfaces involved.&lt;/p>
&lt;p>At some point my system has to bring up an auxiliary service and tell the client which IP and port to connect to. Normally you&amp;rsquo;d handle this with a config file somewhere, but one requirement was that I couldn&amp;rsquo;t assume my own IP, since it could come from any of the network interfaces, and making all of that configurable would get too complex.&lt;/p></description></item><item><title>Differences Between Slice and Array in Go</title><link>https://crg.eti.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/pub/diferencas-entre-slices-e-arrays-golang/</guid><description>&lt;h2 id="array">Array&lt;/h2>
&lt;p>Arrays in Go always have a fixed size.&lt;/p>
&lt;p>When you add a new element to an array, what happens internally is that a new array is created and the old and new items are copied into it. Eventually the space occupied by the old array gets freed by the garbage collector. So it&amp;rsquo;s important, whenever possible, to declare the array with the maximum size it will need and avoid appending items, especially inside a loop.&lt;/p></description></item><item><title>Web Scraping with Golang</title><link>https://crg.eti.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/pub/web-scraping-com-golang/</guid><description>&lt;p>I recently needed to extract some information from a website. My plan was simple: find the URL the search form pointed to, make the request directly from my program, then use the &lt;a href="https://github.com/PuerkitoBio/goquery">goquery&lt;/a> package to parse the results and pull out the data I wanted.&lt;/p>
&lt;p>Of course it wasn&amp;rsquo;t that easy. The site I wanted to crawl was full of JavaScript that interfered with the form, with the cookies, and with basically everything.&lt;/p></description></item><item><title>A Small 8086 CPU Emulator</title><link>https://crg.eti.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/pub/assembly-emulador-8086/</guid><description>&lt;h2 id="8086-emulator-written-in-c">8086 Emulator Written in C&lt;/h2>
&lt;p>The first thing to make clear is that this is not a complete &lt;a href="https://en.wikipedia.org/wiki/Emulator">emulator&lt;/a>. The goal is only to interpret a hello world. Of course, you can take this skeleton and expand it into a full emulator.&lt;/p>
&lt;p>I was bored waiting for my friends to show up at &lt;a href="https://brasil.campus-party.org">Campus Party&lt;/a> 2016. I found the table set aside for the &lt;a href="https://en.wikipedia.org/wiki/Hackerspace">hackerspace&lt;/a> crowd and sat there waiting, but since there were no talks at that hour and nothing else I wanted to attend, I needed something to kill time.&lt;/p></description></item><item><title>Home Office, My Experience Working from Home</title><link>https://crg.eti.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/pub/home-office/</guid><description>&lt;p>Here I&amp;rsquo;ll go over a few things from my experience working from home, along with some tips on how I solved the common problems that anyone who wants to work in tech away from the office will run into.&lt;/p>
&lt;p>I&amp;rsquo;m a veteran when it comes to remote work. I started in the late 90s, back when I worked at a company with a bold, modern management style, especially for Brazil at the time. I was a young programmer with a lot still to learn.&lt;/p></description></item><item><title>BASIC Is Still Alive and Kicking</title><link>https://crg.eti.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/pub/basic-ainda-esta-vivo/</guid><description>&lt;p>While researching BASIC implementations, I found some interesting things. It&amp;rsquo;s amazing that a language this old, and with this many problems, still exists. You can even find commercial compilers still under active development for it.&lt;/p>
&lt;p>Yes, even though I&amp;rsquo;m a fan and love playing with BASIC for the nostalgia and the fun, there&amp;rsquo;s no denying that BASIC causes more problems than it solves. (In my opinion)&lt;/p>
&lt;p>Of course, an extremely simple language made sense when BASIC was born, in 1964. Machines had few resources, and the goal was a language for beginners. BASIC stands for &lt;a href="https://en.wikipedia.org/wiki/BASIC">Beginner&amp;rsquo;s All-Purpose Symbolic Instruction Code&lt;/a>&lt;/p></description></item><item><title>A Tricky Bug with Interfaces and Switch Cases in Go</title><link>https://crg.eti.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/pub/erro-na-ordem-do-switch/</guid><description>&lt;p>Watch the video about this bug on the &lt;a href="https://www.youtube.com/watch?v=v3h024EtxCU">Golang Study Group&lt;/a> channel (in Portuguese).&lt;/p>
&lt;p>Golang is an easy language to program in, and it has few traps for the programmer. Most things that can go wrong are caught by the compiler or by one of the many static analysis tools that help keep our code &lt;em>almost&lt;/em> bug free.&lt;/p>
&lt;p>But there are situations where even those tools have a hard time warning us, because there is no way to know what the programmer expected the program to do. This usually happens when you use the more entertaining features of the language, such as &lt;em>switch&lt;/em>, &lt;em>interfaces&lt;/em>, &lt;em>channels&lt;/em>, and &lt;em>goroutines&lt;/em>.&lt;/p></description></item><item><title>Using goto and labels in Go</title><link>https://crg.eti.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/pub/goto-label-em-golang/</guid><description>&lt;p>The &lt;em>goto&lt;/em> statement has a bad reputation. Back in the BASIC days programmers did not have many options, so they abused &lt;em>goto&lt;/em> and wrote confusing code. Modern languages like Go use goto with judgment and improve code clarity.&lt;/p>
&lt;p>Go lets the &lt;em>break&lt;/em> and &lt;em>continue&lt;/em> statements use labels. Use labels to break out of nested loops or to continue a specific loop. Using &lt;em>break&lt;/em> or &lt;em>continue&lt;/em> with &lt;em>labels&lt;/em> is equivalent to using goto.&lt;/p></description></item><item><title>Protocol Buffers</title><link>https://crg.eti.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/pub/protobuf-com-golang/</guid><description>&lt;p>Watch the video for this article &lt;a href="https://www.youtube.com/watch?v=XzSgREcg_sU">here&lt;/a>.&lt;/p>
&lt;p>This is the first in a series of quick tutorials where I plan to cover &lt;a href="https://grpc.io">gRPC&lt;/a> and various aspects of it, such as testing, TLS, best practices, and much more.&lt;/p>
&lt;p>To get started with gRPC we need to go all the way down to the foundation, so let&amp;rsquo;s talk about &lt;a href="https://developers.google.com/protocol-buffers">Protocol Buffers&lt;/a> first.&lt;/p>
&lt;p>Protocol Buffers is a simple, language-agnostic way to define a data structure. Think XML, but better, simpler, and faster — much faster.&lt;/p></description></item><item><title>JSON, Writing Your Own Marshal and Unmarshal</title><link>https://crg.eti.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/pub/json-parser/</guid><description>&lt;p>Watch the video for this article &lt;a href="https://www.youtube.com/watch?v=ALlzgQfXVFo">here&lt;/a>.&lt;/p>
&lt;p>Postgres&amp;rsquo;s default date format is incompatible with Go&amp;rsquo;s default format, and our system uses JSON heavily to both send and receive information from the database.&lt;/p>
&lt;p>Having to remember to parse the date into the correct format every single time simply isn&amp;rsquo;t practical. It&amp;rsquo;s much better to teach Go how to handle dates and times in good old ISO 8601.&lt;/p>
&lt;p>By the way, I highly recommend always using ISO 8601 UTC for everything in the backend, and only switching to the local format and timezone when displaying it to the user. But that&amp;rsquo;s a story for another day.&lt;/p></description></item><item><title>Interfaces as contracts</title><link>https://crg.eti.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/pub/interface-contrato/</guid><description>&lt;p>Watch the video for this article &lt;a href="https://www.youtube.com/watch?v=ck9rGF0tfRE">here&lt;/a>.&lt;/p>
&lt;p>We covered this same topic in the example list of our study group on interfaces, but that was back in the distant year of 2016, so let&amp;rsquo;s build a new example showing how to use an interface as a contract. The contract lets you pass different types to a function, or accept different types through an interface, as long as they implement it — in other words, as long as they implement the functions described in the interface.&lt;/p></description></item><item><title>The Empty Interface</title><link>https://crg.eti.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/pub/interface-vazia/</guid><description>&lt;p>Watch the video for this article &lt;a href="https://www.youtube.com/watch?v=yBTzaVwqvng">here&lt;/a>.&lt;/p>
&lt;p>The empty interface is a type that accepts anything. You can pass whatever you want as a function parameter or store it in a variable of type &lt;code>interface{}&lt;/code>.&lt;/p>
&lt;p>At first glance this looks convenient, but when we use &lt;code>interface{}&lt;/code> we throw away the type validation done at compile time and lose one of the great advantages of a compiled language with strong, static typing.&lt;/p></description></item><item><title>JSON Tips and Tricks</title><link>https://crg.eti.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/pub/json-golang/</guid><description>&lt;p>Watch the video for this article &lt;a href="https://www.youtube.com/watch?v=0PJ1YqO3wjI">here&lt;/a>.&lt;/p>
&lt;h2 id="converting-and-validating-json">Converting and validating JSON&lt;/h2>
&lt;p>It&amp;rsquo;s always good to check whether the JSON is valid first. That saves you debugging time chasing a problem that isn&amp;rsquo;t in your code. A good online tool for this is &lt;a href="https://jsonlint.com">JSONLint&lt;/a>.&lt;/p>
&lt;p>Another great online tool is &lt;a href="https://mholt.github.io/json-to-go">JSON-to-Go&lt;/a>, which converts JSON files into Go structs. It won&amp;rsquo;t factor repeated parts into sub-structs, but it helps a lot, especially when the structure is large and complex.&lt;/p></description></item><item><title>MS-DOS, APM with C and Assembly</title><link>https://crg.eti.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/pub/apm-msdos-assembly/</guid><description>&lt;p>Watch the video of this article &lt;a href="https://www.youtube.com/watch?v=GTIIId3enis">here&lt;/a>.&lt;/p>
&lt;p>For retrocomputing fun, I use &lt;a href="https://www.virtualbox.org">VirtualBox&lt;/a> with &lt;a href="https://en.wikipedia.org/wiki/MS-DOS">MS-DOS 6.22&lt;/a> and &lt;a href="https://www.dosbox.com">DOSBox&lt;/a>. Both work very well, but the screen looks a bit better in VirtualBox, and DOSBox is faster and easier for developing and switching quickly between systems. So I use both.&lt;/p>
&lt;p>In DOSBox, you can close the emulator by typing the &lt;code>exit&lt;/code> command. That closes a command interpreter session and, if it is the last one, closes DOSBox itself. It is convenient because you do not need the mouse and it behaves more like a terminal.&lt;/p></description></item><item><title>Accessing Dropbox with Golang</title><link>https://crg.eti.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/pub/dropbox-com-golang/</guid><description>&lt;p>I needed a Golang package to talk to Dropbox and perform a few basic operations — listing files, uploading, and downloading. For that I used &lt;a href="https://github.com/dropbox/dropbox-sdk-go-unofficial">dropbox-sdk-go-unofficial&lt;/a>.&lt;/p>
&lt;h2 id="connecting-to-dropbox">Connecting to Dropbox&lt;/h2>
&lt;p>To connect to Dropbox you need access credentials. The easiest way is to create a token: go to &lt;a href="https://www.dropbox.com/developers/apps">Dropbox developers apps&lt;/a>, create an application, and then generate the token from the application&amp;rsquo;s panel.&lt;/p>
&lt;h2 id="configuring-the-system">Configuring the system&lt;/h2>
&lt;p>Every function needs the configuration with the access credentials and other useful parameters, such as the log level. So we create a function that returns an instance of the config struct.&lt;/p></description></item><item><title>Static Compilation with Golang</title><link>https://crg.eti.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/pub/compilacao-estatica-com-golang/</guid><description>&lt;h2 id="building-monolithic-executables">Building monolithic executables&lt;/h2>
&lt;p>Watch the video for this article &lt;a href="https://www.youtube.com/watch?v=kdPWsCTREY8">here&lt;/a>.&lt;/p>
&lt;p>Golang already does a good job of statically compiling almost everything, but depending on your code you may need a few extra flags to make sure your executable is completely free of dependencies.&lt;/p>
&lt;p>The first step is to build your project and then inspect the binary to see whether it has any dependencies.&lt;/p>
&lt;p>On macOS, use the &lt;code>otool&lt;/code> utility (object file displaying tool) with the &lt;code>-L&lt;/code> flag (which lists the &lt;em>shared libraries&lt;/em> in use), like this:&lt;/p></description></item><item><title>Accessing the Serial Port</title><link>https://crg.eti.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/pub/formas-que-uso-para-acessar-porta-serial/</guid><description>&lt;p>Watch the video for this article &lt;a href="https://www.youtube.com/watch?v=4_TqPdyEQVM">here&lt;/a>.&lt;/p>
&lt;p>To me, one of the most interesting things is that the developers deliberately left out some features that screen has, such as telnet and serial port support. They did it because they believe in the &lt;a href="https://en.wikipedia.org/wiki/Unix">UNIX&lt;/a> philosophy of doing one thing and doing it well. In my opinion, they are absolutely right.&lt;/p>
&lt;h2 id="a-few-ways-to-access-the-serial-port">A few ways to access the serial port&lt;/h2>
&lt;p>No matter which method you pick to open the serial port, remember that it is meant to be accessed by only one program at a time. For another program to use the same port, the first one has to close it. This happens a lot when you forget an &lt;a href="https://www.arduino.cc">Arduino&lt;/a> serial terminal session open.&lt;/p></description></item><item><title>A horror story for programmers</title><link>https://crg.eti.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/pub/um-conto-de-terror-para-programadores/</guid><description>&lt;p>Many years ago there was a very famous Linux &lt;a href="https://en.wikipedia.org/wiki/Electronic_mailing_list">mailing list&lt;/a> where everybody hung out. But those were the early days and things were nowhere near as robust as they are today. Mailing lists were still the main way to exchange information because nobody had a 24/7 connection like we do now: you dialed in, downloaded your email, read everything offline, wrote your replies, dialed in again and sent them. Very rough around the edges, but it worked.&lt;/p></description></item><item><title>Golang: Playing with Bits</title><link>https://crg.eti.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/pub/go-brincando-com-bits/</guid><description>&lt;h2 id="playing-with-bits">Playing with bits&lt;/h2>
&lt;p>The idea is to manipulate the CGA color palette, which stores colors in a single byte. This may look complicated, but it is actually very simple: we only need to learn a handful of operations to manipulate bits.&lt;/p>
&lt;p>Before we start, let&amp;rsquo;s agree on the following: when I talk about the upper or high part of a set of bits, I mean the leftmost bits, and when I talk about the lower or low part, I mean the rightmost bits. It is not always like this, but for the purposes of this text that is how it works — this is what we call &lt;a href="https://en.wikipedia.org/wiki/Endianness">lite-endian&lt;/a>&lt;/p></description></item><item><title>Golang defer tips</title><link>https://crg.eti.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/pub/dicas-de-go-defer/</guid><description>&lt;p>Using &lt;a href="https://blog.golang.org/defer-panic-and-recover">defer&lt;/a> to postpone a command until the function returns, no matter how it returns, is an excellent idea. Imagine a function with several return points, either for errors or for a successful finish. Managing the closing of files, connections, mutexes, and other resources at each return becomes tedious and unsafe. You may forget to close a resource on some return path, and that can cause serious problems.&lt;/p>
&lt;p>However, using &lt;code>defer&lt;/code> has a cost. The runtime pushes the deferred command onto a stack, and deferring it is a few nanoseconds slower than a direct call. That is usually not a problem day to day, but if you need to squeeze the most performance out of your code, it may be worth considering.&lt;/p></description></item><item><title>Assembly, assembler, and machine language</title><link>https://crg.eti.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/pub/assembly-assembler-e-linguagem-de-maquina/</guid><description>&lt;h2 id="they-are-different-things">They Are Different Things&lt;/h2>
&lt;p>There are three different but related concepts that people often confuse. Let&amp;rsquo;s clarify each one.&lt;/p>
&lt;h3 id="assembly">Assembly&lt;/h3>
&lt;p>Assembly is a programming language made up of simple mnemonics. It directly corresponds to the instructions of the platform you’re using. When writing Assembly code, you know exactly what the processor is doing and gain access to resources that might not be available in higher-level languages. We can call Assembly a low-level language, meaning it’s closer to the hardware.&lt;/p></description></item></channel></rss>