<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Uthman Oladele</title>
    <description>The latest articles on DEV Community by Uthman Oladele (@uthman_dev).</description>
    <link>https://dev.to/uthman_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3569065%2Fe3bfeb63-9218-4baf-8014-41dbbd3ad9b8.jpg</url>
      <title>DEV Community: Uthman Oladele</title>
      <link>https://dev.to/uthman_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uthman_dev"/>
    <language>en</language>
    <item>
      <title>Stop Writing Bash Scripts, There's a Better Way</title>
      <dc:creator>Uthman Oladele</dc:creator>
      <pubDate>Tue, 03 Mar 2026 07:18:45 +0000</pubDate>
      <link>https://dev.to/uthman_dev/stop-writing-bash-scripts-theres-a-better-way-50en</link>
      <guid>https://dev.to/uthman_dev/stop-writing-bash-scripts-theres-a-better-way-50en</guid>
      <description>&lt;p&gt;If you've ever written a Bash script longer than 30 lines, you know the feeling.&lt;br&gt;
You come back to it a week later and have no idea what it does. Error handling is&lt;br&gt;
a mess of &lt;code&gt;$?&lt;/code&gt; checks, variables are global by default, and debugging feels like&lt;br&gt;
archaeology.&lt;/p&gt;

&lt;p&gt;I got tired of it. But I also didn't want to spin up a Python virtual environment&lt;br&gt;
just to move some files around or hit an API. That felt like overkill.&lt;/p&gt;

&lt;p&gt;So I built Logos.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Logos?
&lt;/h2&gt;

&lt;p&gt;Logos is a small scripting language I wrote in Go. It is designed for the kind of&lt;br&gt;
work Bash handles poorly: readable logic, proper error handling, built-in HTTP and&lt;br&gt;
file operations, and code you can actually come back to a week later.&lt;/p&gt;

&lt;p&gt;It is not trying to replace Python. It is not trying to replace Go. It is just a&lt;br&gt;
tool for that middle ground where Bash becomes unreadable but pulling in a full&lt;br&gt;
language feels like too much.&lt;/p&gt;

&lt;p&gt;Scripts use the &lt;code&gt;.lgs&lt;/code&gt; extension and you run them with the &lt;code&gt;lgs&lt;/code&gt; command.&lt;/p&gt;
&lt;h2&gt;
  
  
  What does it look like?
&lt;/h2&gt;

&lt;p&gt;Here is a simple HTTP request in Logos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let res = httpGet("https://api.example.com/data")

if res.ok {
    let data = parseJson(res.value.body)
    print(data["message"])
} else {
    print("Error: " + res.error)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exceptions. No try/catch. Functions return a result table with &lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;,&lt;br&gt;
and &lt;code&gt;error&lt;/code&gt; fields. You check what you need and move on.&lt;/p&gt;

&lt;p&gt;Compare that to doing the same thing in Bash. You are manually checking exit&lt;br&gt;
codes, parsing curl output with awk, and hoping nothing breaks silently.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why not just use Python?
&lt;/h2&gt;

&lt;p&gt;Python is great. But for quick scripts, you are dealing with virtual environments,&lt;br&gt;
import management, and a language that was not really designed for CLI work. It&lt;br&gt;
also needs to be installed and configured on every machine you run it on.&lt;/p&gt;

&lt;p&gt;Logos ships as a single binary. Install it and run your script. That is it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why not just use Go?
&lt;/h2&gt;

&lt;p&gt;Go requires a compile step. If you are writing a quick script to back up some&lt;br&gt;
files or hit an API, you do not want to set up a module and run &lt;code&gt;go build&lt;/code&gt; every&lt;br&gt;
time you make a change. Logos runs scripts directly, like a shell language should.&lt;/p&gt;

&lt;p&gt;Also, Logos can be embedded inside Go applications as a scripting engine. You can&lt;br&gt;
register Go functions, set variables, and run Logos scripts from within your Go&lt;br&gt;
code. That is something Go itself cannot do cleanly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;vm&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;logos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWithConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SandboxConfig&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;AllowFileIO&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AllowNetwork&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AllowShell&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AllowExit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"greet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;logos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;logos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;logos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;logos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"hello "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`print(greet("world"))`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What can it do?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;File I/O: read, write, copy, move, delete, glob&lt;/li&gt;
&lt;li&gt;HTTP: GET, POST, PATCH, DELETE&lt;/li&gt;
&lt;li&gt;JSON: parse and stringify&lt;/li&gt;
&lt;li&gt;Concurrency: spawn blocks and spawn for-in loops&lt;/li&gt;
&lt;li&gt;A formatter: &lt;code&gt;lgs fmt yourfile.lgs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A compiler: &lt;code&gt;lgs build yourfile.lgs&lt;/code&gt; compiles your script to a standalone binary&lt;/li&gt;
&lt;li&gt;A REPL: just run &lt;code&gt;lgs&lt;/code&gt; with no arguments&lt;/li&gt;
&lt;li&gt;A standard library: math, string, array, path, time, logging, testing, and more&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A real example
&lt;/h2&gt;

&lt;p&gt;Here is a backup script written in Logos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let source = trim(prompt("Source directory: "))

if !fileExists(source) {
    print("Error: " + source + " does not exist")
    exit(1)
}

let dest = trim(prompt("Backup destination: "))
let timestamp = replace(dateTimeStr(), " ", "_")
let backupPath = dest + "/backup_" + timestamp

let result = fileMkdir(backupPath)
if !result.ok {
    print("Failed to create backup directory")
    exit(1)
}

let files = fileReadDir(source)
for entry in files.value {
    fileCopy(source + "/" + entry, backupPath + "/" + entry)
}

print("Backup complete: " + backupPath)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean. Readable. Easy to come back to.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/codetesla51/logos/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works on Linux and macOS. Picks the right binary for your OS and architecture&lt;br&gt;
automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/codetesla51/logos" rel="noopener noreferrer"&gt;https://github.com/codetesla51/logos&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Documentation: &lt;a href="https://logos-lang.vercel.app/docs" rel="noopener noreferrer"&gt;https://logos-lang.vercel.app/docs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have feedback, run into bugs, or want to contribute examples or standard&lt;br&gt;
library utilities, open an issue or a PR. The project is new and I am actively&lt;br&gt;
working on it.&lt;/p&gt;

&lt;p&gt;I built this because I wanted it to exist. Maybe you will find it useful too.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>From Zero to Programming Language: A Complete Implementation Guide</title>
      <dc:creator>Uthman Oladele</dc:creator>
      <pubDate>Sun, 04 Jan 2026 15:19:21 +0000</pubDate>
      <link>https://dev.to/uthman_dev/from-zero-to-programming-language-a-complete-implementation-guide-1mn8</link>
      <guid>https://dev.to/uthman_dev/from-zero-to-programming-language-a-complete-implementation-guide-1mn8</guid>
      <description>&lt;p&gt;Ever wondered how Python, JavaScript, or Go actually work under the hood? I spent months researching and implementing different language designs, and compiled everything into a comprehensive guide that takes you from basic lexical analysis to JIT compilation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;By following this guide, you'll create a complete programming language implementation, starting with a simple calculator and progressively adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lexer &amp;amp; Parser&lt;/strong&gt; - Transform source code into Abstract Syntax Trees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interpreters&lt;/strong&gt; - Direct AST execution (simplest approach)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bytecode VMs&lt;/strong&gt; - Stack-based virtual machines like Python's CPython&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLVM Integration&lt;/strong&gt; - Generate native machine code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage Collection&lt;/strong&gt; - Automatic memory management strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Guide is Different
&lt;/h2&gt;

&lt;p&gt;Most compiler tutorials give you fragments. This gives you &lt;strong&gt;complete, runnable code&lt;/strong&gt; in Go that you can actually execute and modify.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Performance Numbers
&lt;/h3&gt;

&lt;p&gt;No hand-waving here. The guide includes actual benchmarks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tree-Walking Interpreter:  10-100x slower than native
Bytecode VM:              5-50x slower than native
JIT Compiled:             1-5x slower (can match native)
AOT Compiled:             Baseline (native speed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real-world example - Fibonacci(40):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C (gcc -O3): 0.5s&lt;/li&gt;
&lt;li&gt;Python (CPython): 45s (90x slower)&lt;/li&gt;
&lt;li&gt;Python (PyPy JIT): 2.5s (5x slower)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Progressive Learning Path
&lt;/h3&gt;

&lt;p&gt;The guide is structured for gradual complexity:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 1: Build an Interpreter&lt;/strong&gt;&lt;br&gt;
Start with a tree-walking interpreter - the simplest execution model. You'll have a working language by the end of the weekend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 2: Add a Bytecode VM&lt;/strong&gt;&lt;br&gt;
Compile to bytecode and build a stack-based virtual machine. Understand how Python and Java work internally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 3-4: Native Code Generation&lt;/strong&gt;&lt;br&gt;
Use LLVM to generate optimized machine code. Learn what makes Rust and Swift fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beyond: JIT Compilation&lt;/strong&gt;&lt;br&gt;
Study how V8 and HotSpot achieve near-native performance through runtime optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete Working Example
&lt;/h2&gt;

&lt;p&gt;The guide includes a full calculator language implementation with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lexer (tokenization)&lt;/li&gt;
&lt;li&gt;Recursive descent parser&lt;/li&gt;
&lt;li&gt;AST generation&lt;/li&gt;
&lt;li&gt;Tree-walking interpreter&lt;/li&gt;
&lt;li&gt;Variables and expressions
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`
x = 10
y = 20
z = x + y * 2
`&lt;/span&gt;

&lt;span class="n"&gt;lexer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewLexer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lexer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ast&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;interpreter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewInterpreter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;interpreter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"z = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interpreter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"z"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c"&gt;// z = 50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't pseudocode - it's actual running Go code you can build on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Covered
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Compilation Pipeline
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lexical Analysis&lt;/strong&gt;: Breaking source code into tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Syntax Analysis&lt;/strong&gt;: Building Abstract Syntax Trees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Analysis&lt;/strong&gt;: Type checking and symbol resolution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Generation&lt;/strong&gt;: Bytecode, LLVM IR, or direct interpretation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Execution Models Deep Dive
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Interpreters&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Direct AST execution&lt;/li&gt;
&lt;li&gt;Simplest to implement&lt;/li&gt;
&lt;li&gt;Best for scripting and configuration languages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Virtual Machines&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stack-based vs register-based architectures&lt;/li&gt;
&lt;li&gt;Bytecode design and instruction sets&lt;/li&gt;
&lt;li&gt;Function calls and stack frames&lt;/li&gt;
&lt;li&gt;Control flow implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;LLVM Integration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating LLVM IR&lt;/li&gt;
&lt;li&gt;Type system mapping&lt;/li&gt;
&lt;li&gt;Optimization passes&lt;/li&gt;
&lt;li&gt;Cross-platform native code generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;JIT Compilation&lt;/strong&gt; (Advanced)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Profiling and hot path detection&lt;/li&gt;
&lt;li&gt;Runtime code generation&lt;/li&gt;
&lt;li&gt;Deoptimization strategies&lt;/li&gt;
&lt;li&gt;Type specialization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Garbage Collection
&lt;/h3&gt;

&lt;p&gt;Deep dive into automatic memory management:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reference Counting&lt;/strong&gt; - Immediate reclamation, can't handle cycles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mark-and-Sweep&lt;/strong&gt; - Handles cycles, stop-the-world pauses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copying/Generational&lt;/strong&gt; - Best performance, most complex&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each approach includes working implementations and trade-off analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Insights
&lt;/h2&gt;

&lt;p&gt;The guide doesn't just teach theory - it explains practical decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why does Python use bytecode instead of direct interpretation?&lt;/li&gt;
&lt;li&gt;How does JavaScript achieve near-native performance?&lt;/li&gt;
&lt;li&gt;Why are Go compilation times so fast?&lt;/li&gt;
&lt;li&gt;What makes Rust's borrow checker possible?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trade-offs Made Clear
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Development Complexity:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interpreter: Weekend project&lt;/li&gt;
&lt;li&gt;Bytecode VM: 1-2 weeks&lt;/li&gt;
&lt;li&gt;JIT Compiler: Months&lt;/li&gt;
&lt;li&gt;AOT with LLVM: 2-4 weeks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Execution Speed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interpreter: 10-100x slower than native&lt;/li&gt;
&lt;li&gt;Bytecode VM: 5-50x slower&lt;/li&gt;
&lt;li&gt;JIT: 1-5x slower (can match native)&lt;/li&gt;
&lt;li&gt;AOT: Native speed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Startup Time:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interpreter: Instant&lt;/li&gt;
&lt;li&gt;Bytecode VM: Very fast&lt;/li&gt;
&lt;li&gt;JIT: Slow (warmup period)&lt;/li&gt;
&lt;li&gt;AOT: Instant (pre-compiled)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Complete Implementations
&lt;/h3&gt;

&lt;p&gt;Every major component includes full, working code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lexer with position tracking and error handling&lt;/li&gt;
&lt;li&gt;Recursive descent parser with operator precedence&lt;/li&gt;
&lt;li&gt;Stack-based VM with complete instruction set&lt;/li&gt;
&lt;li&gt;LLVM IR generation with control flow&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  No Handwaving
&lt;/h3&gt;

&lt;p&gt;The guide tackles the hard parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to make executable memory for JIT compilation&lt;/li&gt;
&lt;li&gt;Platform-specific calling conventions&lt;/li&gt;
&lt;li&gt;Why reference counting can't handle cycles&lt;/li&gt;
&lt;li&gt;Managing instruction pointer and call stacks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practical Examples
&lt;/h3&gt;

&lt;p&gt;See how to implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Variables and assignments&lt;/li&gt;
&lt;li&gt;Arithmetic expressions with correct precedence&lt;/li&gt;
&lt;li&gt;Control flow (if/while) in bytecode&lt;/li&gt;
&lt;li&gt;Function calls with proper stack frames&lt;/li&gt;
&lt;li&gt;Type checking and semantic analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You should read this if you:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Want to understand how programming languages work&lt;/li&gt;
&lt;li&gt;Are building a DSL or configuration language&lt;/li&gt;
&lt;li&gt;Curious about compiler design but intimidated by Dragon Book&lt;/li&gt;
&lt;li&gt;Want to contribute to language projects (Rust, Go, Python)&lt;/li&gt;
&lt;li&gt;Need to implement a scripting system for your application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comfortable with Go (or can read and adapt the code)&lt;/li&gt;
&lt;li&gt;Basic understanding of data structures (trees, stacks)&lt;/li&gt;
&lt;li&gt;Curiosity about how things work under the hood&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No CS degree required. No prior compiler knowledge assumed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Path Recommendation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with the complete calculator example&lt;/strong&gt; - Get something working immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add control flow&lt;/strong&gt; - Implement if statements and loops using the bytecode examples&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add functions&lt;/strong&gt; - Use the call frame implementation provided&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore LLVM&lt;/strong&gt; - Generate native code when you're ready for more performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Study GC&lt;/strong&gt; - Understand automatic memory management&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each step builds on the previous, and you'll have a working language at each stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Gain
&lt;/h2&gt;

&lt;p&gt;After working through this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deep understanding&lt;/strong&gt; of how interpreters, compilers, and VMs work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical experience&lt;/strong&gt; building complex systems from scratch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Appreciation&lt;/strong&gt; for language design trade-offs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foundation&lt;/strong&gt; for contributing to real language projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidence&lt;/strong&gt; to build domain-specific languages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources Included
&lt;/h2&gt;

&lt;p&gt;The guide references essential learning materials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Crafting Interpreters" by Bob Nystrom&lt;/li&gt;
&lt;li&gt;LLVM tutorials and documentation&lt;/li&gt;
&lt;li&gt;Real-world language implementations to study&lt;/li&gt;
&lt;li&gt;Performance benchmarking techniques&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;The complete guide with all code examples is available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/codetesla51/how-to-build-a-programming-language" rel="noopener noreferrer"&gt;github.com/codetesla51/how-to-build-a-programming-language&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Clone the repo, run the examples, and start building your own language today.&lt;/p&gt;




&lt;h2&gt;
  
  
  Feedback Welcome
&lt;/h2&gt;

&lt;p&gt;This is a living guide. If you find issues, have questions, or want to contribute improvements, please open an issue or PR on GitHub.&lt;/p&gt;

&lt;p&gt;Building a programming language is one of the most rewarding projects in computer science. It demystifies the entire software stack and gives you superpowers for understanding any codebase.&lt;/p&gt;

&lt;p&gt;Start small. Build a calculator. Add features incrementally. Break things. Fix them. That's how you learn.&lt;/p&gt;

&lt;p&gt;Happy language building!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>How Buffer Pooling Doubled My HTTP Server's Throughput (4,000 7,721 RPS)</title>
      <dc:creator>Uthman Oladele</dc:creator>
      <pubDate>Wed, 12 Nov 2025 16:46:35 +0000</pubDate>
      <link>https://dev.to/uthman_dev/how-buffer-pooling-doubled-my-http-servers-throughput-4000-7721-rps-3i0g</link>
      <guid>https://dev.to/uthman_dev/how-buffer-pooling-doubled-my-http-servers-throughput-4000-7721-rps-3i0g</guid>
      <description>&lt;p&gt;Last week, I shared my journey building an HTTP server from scratch in Go using raw TCP sockets. The performance was decent—around 4,000 requests per second at peak—but I knew there was room for improvement.&lt;/p&gt;

&lt;p&gt;Then I learned about &lt;strong&gt;buffer pooling&lt;/strong&gt;, and everything changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Death by a Thousand Allocations
&lt;/h2&gt;

&lt;p&gt;My original server had a hidden performance killer. For every single HTTP request, the server was doing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handleConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// New allocation&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// ... process request ...&lt;/span&gt;
    &lt;span class="c"&gt;// Buffer gets garbage collected&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems innocent, right? But when you're handling thousands of requests per second, this becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Constant memory allocation&lt;/strong&gt; - Creating new 8KB buffers constantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage collector pressure&lt;/strong&gt; - GC running frequently to clean up discarded buffers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU cycles wasted&lt;/strong&gt; - Allocation and deallocation overhead instead of serving requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At 4,000 RPS, my server was allocating and throwing away &lt;strong&gt;32 MB of memory every single second&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Buffer Pooling with sync.Pool
&lt;/h2&gt;

&lt;p&gt;The core idea is brilliantly simple: &lt;strong&gt;reuse buffers instead of creating new ones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Go's standard library provides &lt;code&gt;sync.Pool&lt;/code&gt; for exactly this purpose. Here's how I implemented it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;requestBufferPool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handleConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Get a buffer from the pool&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;requestBufferPool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;requestBufferPool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Return it when done&lt;/span&gt;

    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// ... process request ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request 1: Get buffer from pool → Use it → Return to pool
Request 2: Get SAME buffer → Reset &amp;amp; use → Return to pool
Request 3: Get SAME buffer → Reset &amp;amp; use → Return to pool
                              ↓
                    (Zero new allocations!)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of the old wasteful cycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request 1: Allocate → Use → GC cleanup
Request 2: Allocate → Use → GC cleanup
Request 3: Allocate → Use → GC cleanup
                              ↓
                    (Constant allocation churn)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation: Three Strategic Pools
&lt;/h2&gt;

&lt;p&gt;I identified three hot paths where buffers were being repeatedly allocated:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Request Buffer Pool (8KB)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;requestBufferPool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used for reading incoming HTTP requests from TCP connections.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Chunk Buffer Pool (256 bytes)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;chunkBufferPool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used for smaller, chunked reads during request parsing.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Response Buffer Pool
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;responseBufferPool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used for building HTTP response strings before sending.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results: Nearly 2x Performance Gain
&lt;/h2&gt;

&lt;p&gt;I ran the same benchmark suite before and after implementing buffer pooling:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before Buffer Pools&lt;/th&gt;
&lt;th&gt;After Buffer Pools&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Peak RPS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4,000&lt;/td&gt;
&lt;td&gt;7,721&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;+93%&lt;/strong&gt; 🔥&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Response Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.250ms&lt;/td&gt;
&lt;td&gt;0.130ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;48% faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory Allocations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Constant&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~95% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GC Pressure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Significantly reduced&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Before vs After Comparison
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before (4,000 RPS):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ab &lt;span class="nt"&gt;-n&lt;/span&gt; 10000 &lt;span class="nt"&gt;-c&lt;/span&gt; 10 &lt;span class="nt"&gt;-k&lt;/span&gt; http://localhost:8080/ping

Requests per second:    4000.12 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="c"&gt;#/sec]&lt;/span&gt;
Time per request:       0.250 &lt;span class="o"&gt;[&lt;/span&gt;ms] &lt;span class="o"&gt;(&lt;/span&gt;mean&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (7,721 RPS):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ab &lt;span class="nt"&gt;-n&lt;/span&gt; 10000 &lt;span class="nt"&gt;-c&lt;/span&gt; 10 &lt;span class="nt"&gt;-k&lt;/span&gt; http://localhost:8080/ping

Requests per second:    7721.45 &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="c"&gt;#/sec]&lt;/span&gt;
Time per request:       0.130 &lt;span class="o"&gt;[&lt;/span&gt;ms] &lt;span class="o"&gt;(&lt;/span&gt;mean&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Memory Management Matters—A Lot
&lt;/h3&gt;

&lt;p&gt;Even in a garbage-collected language like Go, being mindful of allocations can dramatically impact performance. The GC is smart, but avoiding work is always faster than doing work efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Profile Before Optimizing
&lt;/h3&gt;

&lt;p&gt;I initially thought my bottleneck was request parsing or routing logic. A quick profiling session revealed that memory allocation was the real culprit.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. sync.Pool Is Your Friend
&lt;/h3&gt;

&lt;p&gt;For any frequently allocated/deallocated objects (buffers, temporary structs, builders), &lt;code&gt;sync.Pool&lt;/code&gt; is a simple way to get significant performance gains.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The 80/20 Rule Applies
&lt;/h3&gt;

&lt;p&gt;Three strategic buffer pools gave me a 93% performance improvement. This took maybe 30 minutes to implement once I understood the concept.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Caveats
&lt;/h2&gt;

&lt;h3&gt;
  
  
  This Is Still a Learning Project
&lt;/h3&gt;

&lt;p&gt;While 7,721 RPS sounds impressive, this benchmark tests a simple &lt;code&gt;/ping&lt;/code&gt; endpoint that returns "pong". Real-world applications with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database queries&lt;/li&gt;
&lt;li&gt;Business logic&lt;/li&gt;
&lt;li&gt;File I/O&lt;/li&gt;
&lt;li&gt;External API calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...will see significantly lower RPS (typically 100-500 for most web apps). Buffer pooling helps with the networking layer, but your application logic will likely be the bottleneck in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not a Silver Bullet
&lt;/h3&gt;

&lt;p&gt;Buffer pooling helps when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're allocating the same size/type repeatedly&lt;/li&gt;
&lt;li&gt;The objects are expensive to create&lt;/li&gt;
&lt;li&gt;Allocation shows up in profiling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It won't help if your bottleneck is CPU-bound computation, database queries, or external API calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Journey So Far
&lt;/h2&gt;

&lt;p&gt;Here's the complete performance evolution of this project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initial buggy version:&lt;/strong&gt; ~250 RPS (Connection handling bugs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bug fix:&lt;/strong&gt; 1,389 RPS (Fixed request handling)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep-alive optimization:&lt;/strong&gt; 1,710 RPS (Connection reuse)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency optimization:&lt;/strong&gt; 4,000 RPS (Found optimal load)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffer pooling:&lt;/strong&gt; 7,721 RPS (Memory optimization) 🚀&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Total improvement: ~31x from the first version!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;The full source code is available on GitHub:&lt;br&gt;
&lt;a href="https://github.com/codetesla51/raw-http" rel="noopener noreferrer"&gt;https://github.com/codetesla51/raw-http&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clone it, run benchmarks before and after commenting out the buffer pools, and see the difference yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/codetesla51/raw-http
&lt;span class="nb"&gt;cd &lt;/span&gt;raw-http
go run main.go

&lt;span class="c"&gt;# In another terminal&lt;/span&gt;
ab &lt;span class="nt"&gt;-n&lt;/span&gt; 10000 &lt;span class="nt"&gt;-c&lt;/span&gt; 10 &lt;span class="nt"&gt;-k&lt;/span&gt; http://localhost:8080/ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Now that I've squeezed significant performance out of the memory layer, I'm curious about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/2 support&lt;/strong&gt; - Binary framing instead of text parsing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection pooling strategies&lt;/strong&gt; - How do production servers handle thousands of concurrent connections?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-copy techniques&lt;/strong&gt; - Can I avoid copying data between buffers entirely?&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Have you used buffer pooling in your projects? What performance gains did you see?&lt;/strong&gt; Drop a comment below—I'd love to hear about your optimization stories!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building from first principles teaches you things frameworks hide. This project continues to surprise me with how much performance can be unlocked by understanding what's really happening under the hood.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Project Stats:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 7,721 RPS peak performance&lt;/li&gt;
&lt;li&gt;🔧 Built with raw TCP sockets in Go&lt;/li&gt;
&lt;li&gt;📚 Learning-focused, not production-ready&lt;/li&gt;
&lt;li&gt;⚡ +93% performance from buffer pooling alone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check out the &lt;a href="https://github.com/codetesla51/raw-http" rel="noopener noreferrer"&gt;full project on GitHub&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>backend</category>
    </item>
    <item>
      <title>Rebuilding Grep in Go: What I Learned About Unix Text Processing</title>
      <dc:creator>Uthman Oladele</dc:creator>
      <pubDate>Tue, 11 Nov 2025 12:04:59 +0000</pubDate>
      <link>https://dev.to/uthman_dev/rebuilding-grep-in-go-what-i-learned-about-unix-text-processing-1oc</link>
      <guid>https://dev.to/uthman_dev/rebuilding-grep-in-go-what-i-learned-about-unix-text-processing-1oc</guid>
      <description>&lt;p&gt;I use grep every day but had no idea how it works. So I built a basic version in Go.&lt;/p&gt;

&lt;p&gt;Not to replace grep. Just to stop being the guy who pipes to grep without understanding what's actually happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;A stripped-down grep that does pattern matching with these flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-i&lt;/code&gt; - Case-insensitive&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[](url)-n&lt;/code&gt; - Line numbers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-c&lt;/code&gt; - Count matches&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-v&lt;/code&gt; - Invert (show non-matches)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-r&lt;/code&gt; - Recursive search&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-l&lt;/code&gt; - Just list filenames&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus binary file detection and color output. That's it. No context lines, no fancy regex modes, no performance optimizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Interesting Parts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Binary Files Don't Print Garbage
&lt;/h3&gt;

&lt;p&gt;When grep hits a binary file (executable, image, whatever), it says "Binary file matches" instead of filling your terminal with nonsense.&lt;/p&gt;

&lt;p&gt;How does it know?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;IsBinary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EOF&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Read 1KB. If there's a null byte (&lt;code&gt;\0&lt;/code&gt;), it's binary. Text files don't have null bytes.&lt;/p&gt;

&lt;p&gt;Simple check. Works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursive Search Without Exploding
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;-r&lt;/code&gt; flag searches directories. This means reading entries, checking if they're files or directories, and recursing when needed.&lt;/p&gt;

&lt;p&gt;The trick: Don't stop on errors. One locked file shouldn't kill your entire search.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Recursive&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s is a directory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error reading directory: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;subCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grepFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"warning: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c"&gt;// Keep going&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;subCount&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log it, move on. Real grep does this. So should you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flags Interact in Weird Ways
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Case-insensitive search:&lt;/strong&gt; Modify the pattern before compiling the regex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CaseInsensitive&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"(?i)"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;List files only:&lt;/strong&gt; Stop after the first match.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;matched&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListFilesOnly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;  &lt;span class="c"&gt;// Done&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Invert match:&lt;/strong&gt; Flip the boolean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;matched&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Invert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;matched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;matched&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Getting these combinations right took a few tries. &lt;code&gt;-r -l&lt;/code&gt; should recurse and list filenames. &lt;code&gt;-v -i&lt;/code&gt; should invert case-insensitive matches. Test all the combinations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Color Output
&lt;/h3&gt;

&lt;p&gt;Grep highlights matches in red. To do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find all regex matches in the line&lt;/li&gt;
&lt;li&gt;Replace each match with a colored version&lt;/li&gt;
&lt;li&gt;Print the result
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;matchColor&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FgRed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SprintFunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;coloredLine&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReplaceAllStringFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;matchColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ReplaceAllStringFunc&lt;/code&gt; walks through matches and applies your function. Easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Actually Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Null bytes are the binary file signal.&lt;/strong&gt; One check, problem solved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compile regex once, use it everywhere.&lt;/strong&gt; Compiling per-line is stupid slow. Compile once at the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scanner vs ReadFile depends on the file type.&lt;/strong&gt; Text files get &lt;code&gt;bufio.Scanner&lt;/code&gt; for line-by-line reading. Binary files get &lt;code&gt;ReadFile&lt;/code&gt; to check the whole thing. Different tools for different jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recursive operations need error tolerance.&lt;/strong&gt; One bad file can't crash everything. Log it, continue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual flag parsing sucks.&lt;/strong&gt; Next time I'm using a library. Checking string prefixes gets old fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Missing
&lt;/h2&gt;

&lt;p&gt;Real grep has a lot more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Context lines (&lt;code&gt;-A&lt;/code&gt;, &lt;code&gt;-B&lt;/code&gt;, &lt;code&gt;-C&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Extended regex (&lt;code&gt;-E&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Fixed string search (&lt;code&gt;-F&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Parallel search&lt;/li&gt;
&lt;li&gt;Memory-mapped files for huge files&lt;/li&gt;
&lt;li&gt;Proper CLI argument parsing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mine doesn't. It does basic pattern matching. That's the point - understand the core, skip the extras.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/codetesla51/go-coreutils.git
&lt;span class="nb"&gt;cd &lt;/span&gt;go-coreutils/grep
go build &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nb"&gt;grep &lt;/span&gt;grep.go
./grep &lt;span class="s2"&gt;"pattern"&lt;/span&gt; file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basic usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./grep &lt;span class="s2"&gt;"error"&lt;/span&gt; logs.txt
./grep &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"warning"&lt;/span&gt; logs.txt
./grep &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"TODO"&lt;/span&gt; ./src
./grep &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"func"&lt;/span&gt; main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Grep is everywhere. Understanding how it works changes how you use it. You stop thinking "magic search command" and start thinking "regex matcher with file handling."&lt;/p&gt;

&lt;p&gt;Plus, now when someone asks "how does grep detect binary files?" you actually know.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/codetesla51/go-coreutils" rel="noopener noreferrer"&gt;github.com/codetesla51/go-coreutils&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More at &lt;a href="https://devuthman.vercel.app" rel="noopener noreferrer"&gt;devuthman.vercel.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>go</category>
    </item>
    <item>
      <title>Building a Terminal Calculator That Actually Does Logic: Axion</title>
      <dc:creator>Uthman Oladele</dc:creator>
      <pubDate>Sun, 09 Nov 2025 12:45:05 +0000</pubDate>
      <link>https://dev.to/uthman_dev/building-a-terminal-calculator-that-actually-does-logic-axion-1p0m</link>
      <guid>https://dev.to/uthman_dev/building-a-terminal-calculator-that-actually-does-logic-axion-1p0m</guid>
      <description>&lt;p&gt;I built a calculator that does more than just add numbers. It's a full mathematical computing environment in your terminal with logical operations, comparison operators, unit conversions, and persistent memory.&lt;/p&gt;

&lt;p&gt;This is an active project - I'm constantly working on it, adding features, fixing bugs, and improving performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build Another Calculator?
&lt;/h2&gt;

&lt;p&gt;Because most CLI calculators are just arithmetic. They add, subtract, maybe handle some trig functions, and that's it.&lt;/p&gt;

&lt;p&gt;I wanted something that could handle real computational work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compare values and return boolean results&lt;/li&gt;
&lt;li&gt;Chain logical operations with proper precedence&lt;/li&gt;
&lt;li&gt;Convert between units without leaving the terminal&lt;/li&gt;
&lt;li&gt;Store variables and reuse them across sessions&lt;/li&gt;
&lt;li&gt;Handle scientific notation properly&lt;/li&gt;
&lt;li&gt;Remember your calculation history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, a calculator that works the way you think, not just the way computers add numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» 2 + 3 &lt;span class="k"&gt;*&lt;/span&gt; 4
Result: 14

» sin&lt;span class="o"&gt;(&lt;/span&gt;30&lt;span class="o"&gt;)&lt;/span&gt; + cos&lt;span class="o"&gt;(&lt;/span&gt;60&lt;span class="o"&gt;)&lt;/span&gt;
Result: 1

» 5 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 3
Result: 1

» &lt;span class="o"&gt;(&lt;/span&gt;5 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 3&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;2 &amp;lt; 4&lt;span class="o"&gt;)&lt;/span&gt;
Result: 1

» x &lt;span class="o"&gt;=&lt;/span&gt; sqrt&lt;span class="o"&gt;(&lt;/span&gt;16&lt;span class="o"&gt;)&lt;/span&gt;
Result: 4

» convert 100 cm to m
100 cm &lt;span class="o"&gt;=&lt;/span&gt; 1 m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not just a calculator - it's a mathematical environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Logical and Comparison Operations
&lt;/h3&gt;

&lt;p&gt;This is what sets Axion apart. You can compare values and chain logical operations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comparison operators:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Returns &lt;code&gt;1&lt;/code&gt; for true, &lt;code&gt;0&lt;/code&gt; for false&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Logical operators:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; (AND) - returns 1 if both operands are non-zero&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;||&lt;/code&gt; (OR) - returns 1 if at least one operand is non-zero&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Proper precedence:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» 0 &lt;span class="o"&gt;||&lt;/span&gt; 1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 0
Result: 0  &lt;span class="c"&gt;# evaluated as: 0 || (1 &amp;amp;&amp;amp; 0)&lt;/span&gt;

» &lt;span class="o"&gt;(&lt;/span&gt;5 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 3&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;2 &amp;lt; 4&lt;span class="o"&gt;)&lt;/span&gt;
Result: 1

» temp &lt;span class="o"&gt;=&lt;/span&gt; 25
» isComfortable &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;temp &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 18&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;temp &amp;lt; 28&lt;span class="o"&gt;)&lt;/span&gt;
Result: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The precedence order matters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;||&lt;/code&gt; (lowest)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Comparison operators&lt;/li&gt;
&lt;li&gt;Arithmetic operators&lt;/li&gt;
&lt;li&gt;Parentheses (highest)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Variable System with Persistence
&lt;/h3&gt;

&lt;p&gt;Variables persist across sessions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» radius &lt;span class="o"&gt;=&lt;/span&gt; 5
Result: 5

» area &lt;span class="o"&gt;=&lt;/span&gt; pi &lt;span class="k"&gt;*&lt;/span&gt; radius^2
Result: 78.5398

» isLarge &lt;span class="o"&gt;=&lt;/span&gt; radius &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; 10
Result: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Close the calculator, open it again, and your variables are still there. Stored in JSON, loaded automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Unit Conversion System
&lt;/h3&gt;

&lt;p&gt;Built-in conversions across three categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Length:&lt;/strong&gt; m, cm, mm, km, in, ft, yd, mi&lt;br&gt;
&lt;strong&gt;Weight:&lt;/strong&gt; kg, g, mg, lb, oz, ton&lt;br&gt;
&lt;strong&gt;Time:&lt;/strong&gt; s, ms, min, h, d&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» convert 5280 ft to mi
5280 ft &lt;span class="o"&gt;=&lt;/span&gt; 1 mi

» convert 2.5 kg to lb
2.5 kg &lt;span class="o"&gt;=&lt;/span&gt; 5.51156 lb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system prevents invalid conversions (like trying to convert kilograms to meters).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Scientific Computing
&lt;/h3&gt;

&lt;p&gt;Full scientific notation support and mathematical functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» 2e-10 + 3.5E+12
Result: 3500000000000

» log&lt;span class="o"&gt;(&lt;/span&gt;100&lt;span class="o"&gt;)&lt;/span&gt; + &lt;span class="nb"&gt;ln&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;e&lt;span class="o"&gt;)&lt;/span&gt; + log2&lt;span class="o"&gt;(&lt;/span&gt;16&lt;span class="o"&gt;)&lt;/span&gt;
Result: 9.60517

» mean&lt;span class="o"&gt;(&lt;/span&gt;10, 20, 30, 40, 50&lt;span class="o"&gt;)&lt;/span&gt;
Result: 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Available functions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trig: &lt;code&gt;sin()&lt;/code&gt;, &lt;code&gt;cos()&lt;/code&gt;, &lt;code&gt;tan()&lt;/code&gt;, &lt;code&gt;asin()&lt;/code&gt;, &lt;code&gt;acos()&lt;/code&gt;, &lt;code&gt;atan()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Log: &lt;code&gt;ln()&lt;/code&gt;, &lt;code&gt;log()&lt;/code&gt;, &lt;code&gt;log10()&lt;/code&gt;, &lt;code&gt;log2()&lt;/code&gt;, custom base with &lt;code&gt;log(x, base)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Stats: &lt;code&gt;mean()&lt;/code&gt;, &lt;code&gt;median()&lt;/code&gt;, &lt;code&gt;mode()&lt;/code&gt;, &lt;code&gt;sum()&lt;/code&gt;, &lt;code&gt;product()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Utility: &lt;code&gt;abs()&lt;/code&gt;, &lt;code&gt;ceil()&lt;/code&gt;, &lt;code&gt;floor()&lt;/code&gt;, &lt;code&gt;round()&lt;/code&gt;, &lt;code&gt;sqrt()&lt;/code&gt;, &lt;code&gt;exp()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Special: factorial with &lt;code&gt;!&lt;/code&gt;, &lt;code&gt;mod()&lt;/code&gt;, &lt;code&gt;print()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Calculation History
&lt;/h3&gt;

&lt;p&gt;Everything you calculate gets stored:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» &lt;span class="nb"&gt;history&lt;/span&gt;
┌─ Calculation History ────────────────────────────┐
│ 2 + 3 &lt;span class="k"&gt;*&lt;/span&gt; 4                    &lt;span class="o"&gt;=&lt;/span&gt; 14
│ sin&lt;span class="o"&gt;(&lt;/span&gt;30&lt;span class="o"&gt;)&lt;/span&gt; + cos&lt;span class="o"&gt;(&lt;/span&gt;60&lt;span class="o"&gt;)&lt;/span&gt;            &lt;span class="o"&gt;=&lt;/span&gt; 1
│ x &lt;span class="o"&gt;=&lt;/span&gt; sqrt&lt;span class="o"&gt;(&lt;/span&gt;16&lt;span class="o"&gt;)&lt;/span&gt;                 &lt;span class="o"&gt;=&lt;/span&gt; 4
│ convert 100 cm to m          &lt;span class="o"&gt;=&lt;/span&gt; 1 m
└──────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stored in JSON, persists across sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;Axion uses a proper compiler-style pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Input
    ↓
Tokenizer → Breaks input into tokens (numbers, operators, functions)
    ↓
Parser → Builds Abstract Syntax Tree (AST) with proper precedence
    ↓
Evaluator → Walks the AST and computes the result
    ↓
Output → Color-coded terminal display
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Parser
&lt;/h3&gt;

&lt;p&gt;This was the hardest part. Getting operator precedence right took multiple attempts.&lt;/p&gt;

&lt;p&gt;The parser uses recursive descent with precedence climbing. Each precedence level gets its own parsing function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Simplified version&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;parseExpression&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parseLogicalOr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c"&gt;// Lowest precedence&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;parseLogicalOr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parseLogicalAnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// Handle || operators&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;parseLogicalAnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parseComparison&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// Handle &amp;amp;&amp;amp; operators&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;parseComparison&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parseAddition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// Handle &amp;gt;, &amp;lt;, ==, etc.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// And so on...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure ensures &lt;code&gt;2 + 3 &amp;gt; 4 || 0&lt;/code&gt; parses correctly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parse &lt;code&gt;2 + 3&lt;/code&gt; (addition has higher precedence)&lt;/li&gt;
&lt;li&gt;Parse &lt;code&gt;&amp;gt; 4&lt;/code&gt; (comparison)&lt;/li&gt;
&lt;li&gt;Parse &lt;code&gt;|| 0&lt;/code&gt; (logical OR has lowest precedence)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Token Types
&lt;/h3&gt;

&lt;p&gt;The tokenizer recognizes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NUMBER&lt;/code&gt; - integers, decimals, scientific notation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OPERATOR&lt;/code&gt; - &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;, &lt;code&gt;!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COMPARISON&lt;/code&gt; - &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LOGICAL&lt;/code&gt; - &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FUNCTION&lt;/code&gt; - &lt;code&gt;sin&lt;/code&gt;, &lt;code&gt;cos&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LPAREN&lt;/code&gt;/&lt;code&gt;RPAREN&lt;/code&gt; - parentheses for grouping&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COMMA&lt;/code&gt; - function argument separator&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Evaluator
&lt;/h3&gt;

&lt;p&gt;Walks the AST recursively. Each node type has its own evaluation logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;NODE_NUMBER&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;NODE_OPERATOR&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;applyOperator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;NODE_COMPARISON&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;compareValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;  &lt;span class="c"&gt;// true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0.0&lt;/span&gt;  &lt;span class="c"&gt;// false&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;NODE_AND&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0.0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comparisons and logical operations return &lt;code&gt;1.0&lt;/code&gt; (true) or &lt;code&gt;0.0&lt;/code&gt; (false), which lets you use them in further calculations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Physics Calculations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» F &lt;span class="o"&gt;=&lt;/span&gt; 9.8 &lt;span class="k"&gt;*&lt;/span&gt; 75  &lt;span class="c"&gt;# Force = mass * acceleration&lt;/span&gt;
Result: 735

» isValidForce &lt;span class="o"&gt;=&lt;/span&gt; F &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 0 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; F &amp;lt; 1000
Result: 1

» E &lt;span class="o"&gt;=&lt;/span&gt; F &lt;span class="k"&gt;*&lt;/span&gt; 10    &lt;span class="c"&gt;# Energy = force * distance&lt;/span&gt;
Result: 7350
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Financial Math
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» principal &lt;span class="o"&gt;=&lt;/span&gt; 1000
» rate &lt;span class="o"&gt;=&lt;/span&gt; 0.05
» compoundInterest &lt;span class="o"&gt;=&lt;/span&gt; principal &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;1 + rate&lt;span class="o"&gt;)&lt;/span&gt;^10
Result: 1628.89

» isProfit &lt;span class="o"&gt;=&lt;/span&gt; compoundInterest &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; principal
Result: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Engineering
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» voltage &lt;span class="o"&gt;=&lt;/span&gt; 12
» current &lt;span class="o"&gt;=&lt;/span&gt; 2.5
» power &lt;span class="o"&gt;=&lt;/span&gt; voltage &lt;span class="k"&gt;*&lt;/span&gt; current
Result: 30

» resistance &lt;span class="o"&gt;=&lt;/span&gt; voltage / current
Result: 4.8

» isSafeVoltage &lt;span class="o"&gt;=&lt;/span&gt; voltage &amp;lt; 50
Result: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Axion/
├── main.go              # Entry point
├── cmd/                 # Cobra CLI commands
│   └── cmd.go          # REPL implementation
├── tokenizer/          # Lexical analysis
│   └── tokenizer.go
├── parser/             # Syntax analysis
│   └── parser.go
├── evaluator/          # Expression evaluation
│   └── evaluator.go
├── units/              # Unit conversion
│   └── units.go
├── history/            # History management
│   └── history.go
└── constants/          # Constants loading
    └── constants.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each module has a single responsibility. The Cobra framework handles CLI commands and the interactive REPL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Coverage
&lt;/h2&gt;

&lt;p&gt;Core computational modules have solid test coverage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Units:&lt;/strong&gt; 100% (unit conversion system)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokenizer:&lt;/strong&gt; 94% (lexical analysis)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parser:&lt;/strong&gt; 76.4% (AST construction)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluator:&lt;/strong&gt; 74.5% (mathematical computation)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The utility modules (constants, history, settings) and CLI handlers don't have tests yet. They're next on the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Quick install (Linux/macOS):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/codetesla51/Axion.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Axion
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x install.sh
./install.sh
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script builds the binary, creates a symlink in &lt;code&gt;~/.local/bin&lt;/code&gt;, and adds it to your PATH.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/codetesla51/Axion.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Axion
go build &lt;span class="nt"&gt;-o&lt;/span&gt; axion
./axion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Operator precedence is harder than it looks.&lt;/strong&gt; Getting &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; to bind tighter than &lt;code&gt;||&lt;/code&gt; while both bind looser than comparisons required multiple parsing passes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recursive descent parsing is elegant.&lt;/strong&gt; Once you understand the pattern (each precedence level calls the next higher level), it's straightforward to extend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Cobra framework is powerful.&lt;/strong&gt; Building a CLI with subcommands, flags, and help text is trivial with Cobra. Would have taken way longer without it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing matters.&lt;/strong&gt; The bugs I caught with unit tests would have been nightmares to debug in production. Writing tests as you go saves time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON is good enough for most storage needs.&lt;/strong&gt; No need for a database when you're just storing variables and history. JSON files work fine and are human-readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Potential additions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Matrix operations&lt;/li&gt;
&lt;li&gt;Complex numbers&lt;/li&gt;
&lt;li&gt;Custom function definitions&lt;/li&gt;
&lt;li&gt;Graphing capabilities&lt;/li&gt;
&lt;li&gt;More unit categories (temperature, pressure, etc.)&lt;/li&gt;
&lt;li&gt;Export calculations to different formats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the core is solid. It does what it needs to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/codetesla51/Axion.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Axion
./install.sh
axion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then try some calculations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;» x &lt;span class="o"&gt;=&lt;/span&gt; 10
» y &lt;span class="o"&gt;=&lt;/span&gt; 20
» &lt;span class="o"&gt;(&lt;/span&gt;x &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 5&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;y &amp;lt; 25&lt;span class="o"&gt;)&lt;/span&gt;
Result: 1

» convert 5 km to mi
5 km &lt;span class="o"&gt;=&lt;/span&gt; 3.10686 mi

» print&lt;span class="o"&gt;(&lt;/span&gt;sin&lt;span class="o"&gt;(&lt;/span&gt;45&lt;span class="o"&gt;))&lt;/span&gt;
0.707107
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Built with Go and Cobra.&lt;/strong&gt; Full source on &lt;a href="https://github.com/codetesla51/Axion" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out more at &lt;a href="https://devuthman.vercel.app" rel="noopener noreferrer"&gt;devuthman.vercel.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building Git from Scratch in Go: What I Learned About Version Control Internals</title>
      <dc:creator>Uthman Oladele</dc:creator>
      <pubDate>Sun, 09 Nov 2025 12:36:05 +0000</pubDate>
      <link>https://dev.to/uthman_dev/building-git-from-scratch-in-go-what-i-learned-about-version-control-internals-4dih</link>
      <guid>https://dev.to/uthman_dev/building-git-from-scratch-in-go-what-i-learned-about-version-control-internals-4dih</guid>
      <description>&lt;p&gt;I didn't understand Git until I broke it open and rebuilt it from scratch. No libraries, no shortcuts - just SHA-256 hashing, tree structures, and commit graphs.&lt;/p&gt;

&lt;p&gt;I built a Git implementation in Go without using any Git libraries. No magic, just content-addressable storage and the object model. It works, it taught me more about Git in a week than years of using it, and here's what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Learned This
&lt;/h2&gt;

&lt;p&gt;This wasn't from a single source. I pieced it together from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CodeCrafters&lt;/strong&gt; - Their "Build Your Own Git" challenge gave me the structure and pushed me to actually implement things&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Random YouTube videos&lt;/strong&gt; - Honestly, just searching "how git works internally" and watching whatever came up. Some were helpful, most weren't&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Building Git" book&lt;/strong&gt; - Wasn't really helpful for what I needed, but it did clarify some object format details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of the learning came from trial and error. Breaking things, reading error messages, and debugging for hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build This?
&lt;/h2&gt;

&lt;p&gt;I use Git every day but had no idea how it actually works. Just &lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt;, and hope nothing breaks. I wanted to understand what's really happening under the hood.&lt;/p&gt;

&lt;p&gt;The goal wasn't to make something production-ready. I just wanted answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why are commits so cheap?&lt;/li&gt;
&lt;li&gt;How does Git deduplicate files automatically?&lt;/li&gt;
&lt;li&gt;What the hell is a "tree object"?&lt;/li&gt;
&lt;li&gt;Why is branching fast?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Turns out the best way to understand something is to build it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;Go-Git implements the core stuff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go-git init                    &lt;span class="c"&gt;# Initialize repository&lt;/span&gt;
go-git config                  &lt;span class="c"&gt;# Set user identity&lt;/span&gt;
go-git add &amp;lt;files...&amp;gt;          &lt;span class="c"&gt;# Stage files&lt;/span&gt;
go-git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"message"&lt;/span&gt;     &lt;span class="c"&gt;# Create commit&lt;/span&gt;
go-git log                     &lt;span class="c"&gt;# View history&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It handles content-addressable storage, the staging area, tree objects, commit history, and zlib compression. Basically everything Git does to manage your code, minus branches, merges, and remotes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Main Ideas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Content-Addressable Storage
&lt;/h3&gt;

&lt;p&gt;Every object (file, directory, commit) gets stored by its SHA-256 hash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.git/objects/ab/c123def456...
            ↑↑  ↑↑↑↑↑↑↑
            │   └─ Rest of hash (filename)
            └───── First 2 chars (subdirectory)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is actually genius. Same content = same hash = automatic deduplication. You could store the same &lt;code&gt;README.md&lt;/code&gt; across 100 commits and it only takes up disk space once.&lt;/p&gt;

&lt;p&gt;Your file's hash IS its address. No need for a separate indexing system.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Three Trees
&lt;/h3&gt;

&lt;p&gt;Git tracks files through three layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Working Directory  →  Staging Area  →  Repository
   (your files)        (.git/index)     (.git/objects)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;go-git add&lt;/code&gt; moves files from working directory → staging area&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;go-git commit&lt;/code&gt; snapshots staging area → repository&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The staging area is literally just a text file mapping paths to hashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100644 abc123... README.md
100644 def456... src/main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you commit, Git hashes this whole thing into a tree object.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Tree Objects (The Hard Part)
&lt;/h3&gt;

&lt;p&gt;Files get stored as &lt;strong&gt;blobs&lt;/strong&gt;. Directories get stored as &lt;strong&gt;trees&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Simple project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
  README.md
  src/
    main.go
    lib/
      helper.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git stores it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Commit (abc123)
    ↓
Root Tree (def456)
├─ blob: README.md (hash: abc123)
└─ tree: src/ (hash: def456)
      ├─ blob: main.go (hash: ghi789)
      └─ tree: lib/ (hash: jkl012)
            └─ blob: helper.go (hash: mno345)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what finally clicked for me: &lt;strong&gt;Trees don't contain their children - they just reference them by hash.&lt;/strong&gt; That's why Git is fast. If a directory doesn't change, same hash, just reuse the tree. No need to re-store anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tricky part:&lt;/strong&gt; You have to build trees bottom-up (deepest first) because parent trees need their children's hashes.&lt;/p&gt;

&lt;p&gt;You can't hash &lt;code&gt;src/&lt;/code&gt; until you know the hash of &lt;code&gt;src/lib/&lt;/code&gt;. Can't hash the root tree until you know the hash of &lt;code&gt;src/&lt;/code&gt;. The order matters, period.&lt;/p&gt;

&lt;p&gt;This took me over 5 hours to get right.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Was Hard
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tree Building Order
&lt;/h3&gt;

&lt;p&gt;First try: Build trees top-down, starting from root. Immediately failed - you don't have the child tree hashes yet.&lt;/p&gt;

&lt;p&gt;Fix: Sort directories by depth, build the deepest ones first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then for each directory, check if any trees you've already built are its children and add them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Binary vs Hex Encoding
&lt;/h3&gt;

&lt;p&gt;Tree objects store hashes as 32 binary bytes, not 64-character hex strings.&lt;/p&gt;

&lt;p&gt;My bug:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BlobHash&lt;/span&gt;  &lt;span class="c"&gt;// Wrong! This is a 64-char hex string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;hashBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DecodeString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BlobHash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashBytes&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// 32 binary bytes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made my trees twice as big as they should've been. Spent an hour debugging because it was subtle - objects were still readable but tree traversal was completely broken.&lt;/p&gt;

&lt;h3&gt;
  
  
  Excluding .git/ When Staging
&lt;/h3&gt;

&lt;p&gt;When you do &lt;code&gt;go-git add .&lt;/code&gt;, you don't want to accidentally add &lt;code&gt;.git/objects/&lt;/code&gt; to the index.&lt;/p&gt;

&lt;p&gt;First attempt: Check if the path contains &lt;code&gt;.git&lt;/code&gt;. Problem: this also excluded files like &lt;code&gt;my.git.file&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The right way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;".git"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SkipDir&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;filepath.SkipDir&lt;/code&gt; during directory traversal is the way to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Objects Work
&lt;/h2&gt;

&lt;p&gt;Every object follows this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt; &amp;lt;size&amp;gt;\0&amp;lt;content&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gets compressed with zlib, stored at &lt;code&gt;.git/objects/&amp;lt;hash[:2]&amp;gt;/&amp;lt;hash[2:]&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blob:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;blob 13\0Hello, World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hash it → &lt;code&gt;a0b1c2d3...&lt;/code&gt; → Store at &lt;code&gt;.git/objects/a0/b1c2d3...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tree:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tree 74\0100644 README.md\0&amp;lt;32-byte-hash&amp;gt;040000 src\0&amp;lt;32-byte-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;100644&lt;/code&gt; = regular file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;040000&lt;/code&gt; = directory (tree object)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Commit:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commit &amp;lt;size&amp;gt;\0
tree abc123...
parent 789xyz...
author Uthman &amp;lt;email&amp;gt; timestamp
committer Uthman &amp;lt;email&amp;gt; timestamp

Initial commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commits form a directed acyclic graph. &lt;code&gt;go-git log&lt;/code&gt; just walks backwards through this chain from HEAD.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Actually Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Content-addressable storage is elegant.&lt;/strong&gt; Hash = address. This one idea enables deduplication, integrity checking, and efficient storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trees are graphs, not nested structures.&lt;/strong&gt; A tree object doesn't "contain" subtrees - it references them by hash. This indirection is what makes Git efficient. Multiple commits can share the same tree if a directory didn't change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building bottom-up is necessary.&lt;/strong&gt; You can't hash a parent without knowing its children's hashes. The order matters fundamentally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compression matters.&lt;/strong&gt; Without zlib, &lt;code&gt;.git/objects/&lt;/code&gt; would be 3-4x larger. Git uses compression everywhere for a reason.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Binary formats are tricky.&lt;/strong&gt; Working with &lt;code&gt;\0&lt;/code&gt; null bytes and binary hash data requires careful handling. Text formats would be easier but less efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Missing
&lt;/h2&gt;

&lt;p&gt;This is a learning project, not production software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No branches (only &lt;code&gt;main&lt;/code&gt; exists)&lt;/li&gt;
&lt;li&gt;No merge operations&lt;/li&gt;
&lt;li&gt;No diff/status commands&lt;/li&gt;
&lt;li&gt;No remote operations (push/pull/fetch)&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;.gitignore&lt;/code&gt; support&lt;/li&gt;
&lt;li&gt;No packed objects (each object is a separate file)&lt;/li&gt;
&lt;li&gt;Plain text index (real Git uses binary format)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These limitations exist because this project focuses on Git's core: the object model, staging, and commits. Adding branches/merging/remotes would be another 2-3x the code and shift focus from fundamentals to features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/codetesla51/go-git.git
&lt;span class="nb"&gt;cd &lt;/span&gt;go-git
./install.sh

&lt;span class="c"&gt;# Or build manually:&lt;/span&gt;
go build &lt;span class="nt"&gt;-buildvcs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; go-git
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/go-git ~/.local/bin/go-git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-project
&lt;span class="nb"&gt;cd &lt;/span&gt;my-project
go-git init
go-git config

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; README.md
go-git add README.md
go-git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
go-git log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Want to really learn?&lt;/strong&gt; Clone it, break something on purpose (change the hash function to MD5, remove zlib compression), and see what fails. Watch how Git's assumptions about immutability and content-addressing cascade through the system. That's how you really understand it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building this taught me more about Git in a week than years of using it did. I now understand why commits are cheap (just pointers to trees), how deduplication works (content-addressable storage), and why branching is fast (just moving a pointer).&lt;/p&gt;

&lt;p&gt;If you want to truly understand a tool, build it yourself.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Built with Go, no Git libraries used.&lt;/strong&gt; All hashing, compression, and object storage is custom implementation.&lt;/p&gt;

&lt;p&gt;Check out more of my work at &lt;a href="https://devuthman.vercel.app" rel="noopener noreferrer"&gt;devuthman.vercel.app&lt;/a&gt; | &lt;a href="https://github.com/codetesla51/go-git" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cli</category>
      <category>git</category>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building an HTTP Server from TCP Sockets: 250 4,000 RPS</title>
      <dc:creator>Uthman Oladele</dc:creator>
      <pubDate>Fri, 07 Nov 2025 12:59:48 +0000</pubDate>
      <link>https://dev.to/uthman_dev/building-an-http-server-from-tcp-sockets-250-4000-rps-2m93</link>
      <guid>https://dev.to/uthman_dev/building-an-http-server-from-tcp-sockets-250-4000-rps-2m93</guid>
      <description>&lt;p&gt;Most developers use frameworks like Express or Flask without understanding what happens underneath. I built an HTTP/HTTPS server from raw TCP sockets in Go to learn how web servers actually work - no frameworks, just socket programming and protocol implementation.&lt;/p&gt;

&lt;p&gt;The result? A journey from 250 RPS with buggy connection handling to 4,000 RPS at peak performance. Here's how I did it and what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build This?
&lt;/h2&gt;

&lt;p&gt;I wanted to understand HTTP at the protocol level - not just use it through abstractions. What does "parsing a request" actually mean? How does keep-alive work? What makes one server faster than another?&lt;/p&gt;

&lt;p&gt;Building from TCP sockets up forced me to learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How HTTP requests are structured byte-by-byte&lt;/li&gt;
&lt;li&gt;Connection lifecycle and reuse patterns&lt;/li&gt;
&lt;li&gt;TLS/SSL encryption from first principles&lt;/li&gt;
&lt;li&gt;Why implementation details matter for performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;A lightweight HTTP/HTTPS server that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parses HTTP requests directly from TCP socket connections&lt;/li&gt;
&lt;li&gt;Routes requests with custom method and path matching&lt;/li&gt;
&lt;li&gt;Serves static files with proper MIME type detection&lt;/li&gt;
&lt;li&gt;Supports HTTP/1.1 keep-alive for connection reuse&lt;/li&gt;
&lt;li&gt;Handles form data and JSON request bodies&lt;/li&gt;
&lt;li&gt;Includes optional TLS encryption for HTTPS&lt;/li&gt;
&lt;li&gt;Achieves 4,000 requests per second at peak&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tech stack:&lt;/strong&gt; Pure Go, no web frameworks. Just &lt;code&gt;net&lt;/code&gt; package for TCP, &lt;code&gt;crypto/tls&lt;/code&gt; for HTTPS, and &lt;code&gt;html/template&lt;/code&gt; for rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Performance Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Initial Version: 250 RPS (Buggy)
&lt;/h3&gt;

&lt;p&gt;My first implementation had a critical bug in request processing combined with &lt;code&gt;Connection: close&lt;/code&gt; on every response. The server worked but was crawling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug Fix: 1,389 RPS
&lt;/h3&gt;

&lt;p&gt;Fixed the request handling logic but still sent &lt;code&gt;Connection: close&lt;/code&gt; on every response. This meant every request required a new TCP handshake - expensive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep-Alive Implementation: 1,710 RPS
&lt;/h3&gt;

&lt;p&gt;Added proper HTTP/1.1 keep-alive support. Connections stayed open for multiple requests. Immediate improvement but not optimal yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Peak Performance: 4,000 RPS
&lt;/h3&gt;

&lt;p&gt;Discovered that concurrency level matters significantly. At 10 concurrent connections with connection reuse, the server hit 4,000 RPS with 0.252ms response times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total improvement: 16x from initial version&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Actually Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. TCP Connection Handling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;handleConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// One goroutine per connection&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each connection gets its own goroutine. Go's scheduler handles thousands of these efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. HTTP Request Parsing
&lt;/h3&gt;

&lt;p&gt;Reading from the socket gives you raw bytes. You need to parse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request line: &lt;code&gt;GET /path HTTP/1.1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Headers: &lt;code&gt;Content-Type: application/json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Body: Form data or JSON payload
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;parseRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Read request line&lt;/span&gt;
    &lt;span class="n"&gt;requestLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Parse method, path, version&lt;/span&gt;
    &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestLine&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"invalid request line"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c"&gt;// Read headers until empty line&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// Parse header: "Content-Type: application/json"&lt;/span&gt;
        &lt;span class="c"&gt;// ... header parsing logic&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Keep-Alive Implementation
&lt;/h3&gt;

&lt;p&gt;The breakthrough came from proper connection reuse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handleConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;parseRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="c"&gt;// Connection closed or invalid request&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// Send response with keep-alive&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"HTTP/1.1 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connection: keep-alive&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Length: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c"&gt;// Connection stays open for next request&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Connection"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"close"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple change - keeping connections open - improved performance by 23% (1,389 → 1,710 RPS).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Routing System
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Router&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;routes&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt; &lt;span class="c"&gt;// method -&amp;gt; path -&amp;gt; handler&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;createResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;createResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"404"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Not Found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. HTTPS/TLS Support
&lt;/h3&gt;

&lt;p&gt;Adding TLS was surprisingly straightforward with Go's &lt;code&gt;crypto/tls&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadX509KeyPair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"server.crt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"server.key"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Certificates&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":8443"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Same connection handling as HTTP&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;handleConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The TLS layer handles encryption/decryption transparently. Your HTTP parsing code stays the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Analysis
&lt;/h2&gt;

&lt;p&gt;Testing with different concurrency levels revealed interesting patterns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concurrency&lt;/th&gt;
&lt;th&gt;RPS&lt;/th&gt;
&lt;th&gt;Response Time&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;4,000&lt;/td&gt;
&lt;td&gt;0.252ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Peak performance&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;2,926&lt;/td&gt;
&lt;td&gt;0.342ms&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;2,067&lt;/td&gt;
&lt;td&gt;0.484ms&lt;/td&gt;
&lt;td&gt;Very good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;2,286&lt;/td&gt;
&lt;td&gt;0.437ms&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;1,463&lt;/td&gt;
&lt;td&gt;0.683ms&lt;/td&gt;
&lt;td&gt;Moderate load&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key insights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sweet spot: 10-200 concurrent connections&lt;/li&gt;
&lt;li&gt;Sub-millisecond response times at low concurrency&lt;/li&gt;
&lt;li&gt;0% failure rate across all tests&lt;/li&gt;
&lt;li&gt;Connection reuse was the single biggest optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example Usage
&lt;/h2&gt;

&lt;p&gt;Here's how you'd use this server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;// Simple API endpoint&lt;/span&gt;
&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/plain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pong"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c"&gt;// Form handling with browser detection&lt;/span&gt;
&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Browser&lt;/span&gt; &lt;span class="c"&gt;// Parsed from User-Agent&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Welcome "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;"!&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;Browser: "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;/p&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"401"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Unauthorized"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Login Failed&amp;lt;/h1&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quick start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/codetesla51/raw-http
&lt;span class="nb"&gt;cd &lt;/span&gt;raw-http
go mod tidy
go run main.go

&lt;span class="c"&gt;# Test it&lt;/span&gt;
curl http://localhost:8080/ping
&lt;span class="c"&gt;# Returns: pong&lt;/span&gt;

curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/login &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"username=admin&amp;amp;password=secret"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. HTTP Is Just Text Over TCP
&lt;/h3&gt;

&lt;p&gt;Seeing the raw bytes demystified HTTP completely. It's not magic - just structured text following a protocol.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Connection Reuse Matters
&lt;/h3&gt;

&lt;p&gt;The jump from 1,389 to 1,710 RPS came purely from keeping connections open. TCP handshakes are expensive.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Concurrency Level Impacts Performance
&lt;/h3&gt;

&lt;p&gt;More concurrent connections doesn't always mean better performance. The server performed best at 10-200 concurrent requests, then degraded at higher levels.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Go's Concurrency Model Shines
&lt;/h3&gt;

&lt;p&gt;One goroutine per connection is simple and scales well. No need for complex event loops or worker pools.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. TLS/SSL Is Less Scary Than It Seems
&lt;/h3&gt;

&lt;p&gt;With proper libraries, adding encryption is straightforward. The protocol complexity is handled for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Security Requires Constant Attention
&lt;/h3&gt;

&lt;p&gt;Path traversal protection, request size limits, and proper error handling are essential. Easy to miss when building from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;This is a learning project, not production software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic error handling&lt;/li&gt;
&lt;li&gt;Simple routing (no regex or path parameters)&lt;/li&gt;
&lt;li&gt;No middleware system&lt;/li&gt;
&lt;li&gt;Limited HTTP method support&lt;/li&gt;
&lt;li&gt;Self-signed certificates only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But that's the point - understanding fundamentals before adding features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;The full source code is on GitHub: &lt;a href="https://github.com/codetesla51/raw-http" rel="noopener noreferrer"&gt;codetesla51/raw-http&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Routes to try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; - Home page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/ping&lt;/code&gt; - Simple API endpoint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/login&lt;/code&gt; - Form handling demo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/welcome&lt;/code&gt; - Template rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For HTTPS (port 8443), the repo includes self-signed certificates for testing. For production, use Let's Encrypt or another CA.&lt;/p&gt;

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

&lt;p&gt;Building an HTTP server from TCP sockets taught me more about web programming in a week than years of using frameworks. The 16x performance improvement wasn't just about optimization - it was about understanding what actually makes servers fast.&lt;/p&gt;

&lt;p&gt;If you're curious about how the tools you use every day actually work, I highly recommend building them yourself. Start small, measure everything, and don't be afraid to make mistakes. My first version was buggy and slow, but that's how you learn.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;More projects:&lt;/strong&gt; &lt;a href="https://devuthman.vercel.app" rel="noopener noreferrer"&gt;devuthman.vercel.app&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Source code:&lt;/strong&gt; &lt;a href="https://github.com/codetesla51/raw-http" rel="noopener noreferrer"&gt;github.com/codetesla51/raw-http&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built with Go 1.21+ • Created by Uthman&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
