<?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>Forem: Trung Duong</title>
    <description>The latest articles on Forem by Trung Duong (@trungdlp).</description>
    <link>https://forem.com/trungdlp</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%2F2812367%2Fb9330437-0793-4ff6-af13-23233695d2c6.jpg</url>
      <title>Forem: Trung Duong</title>
      <link>https://forem.com/trungdlp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/trungdlp"/>
    <language>en</language>
    <item>
      <title>😴 Go Code You Can Trust: Sleep Well After You Commit</title>
      <dc:creator>Trung Duong</dc:creator>
      <pubDate>Thu, 13 Mar 2025 03:11:52 +0000</pubDate>
      <link>https://forem.com/trungdlp/go-code-you-can-trust-sleep-well-after-you-commit-440n</link>
      <guid>https://forem.com/trungdlp/go-code-you-can-trust-sleep-well-after-you-commit-440n</guid>
      <description>&lt;p&gt;It's Friday afternoon, 4:45 PM. My teammates are already discussing weekend plans in Slack. I'm finishing up a critical piece of our payment processing service. The code is done, tests pass, and I'm about to commit it before heading into the weekend. My finger hovers over the enter key for a moment...&lt;/p&gt;

&lt;p&gt;But there's no hesitation, no worry. I commit the code, close my laptop, and join the weekend conversation without a second thought about my code failing in production.&lt;/p&gt;

&lt;p&gt;This wasn't always the case. Ten years ago, I'd be checking my phone all weekend, worried about 3 AM calls from our on-call engineer.&lt;/p&gt;

&lt;p&gt;What changed? Let me tell you my story of how I learned to write Go code I could trust completely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn393n409zl98ytlzccj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn393n409zl98ytlzccj.png" alt="Golang sleep" width="512" height="512"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image source: Medium&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Cost of Uncertain Code
&lt;/h2&gt;

&lt;p&gt;My journey with Go started in 2021 when I was working at a rapidly growing startup. We were moving from a monolithic Java application to microservices, and Go seemed like the perfect fit: fast, simple, and with built-in concurrency.&lt;/p&gt;

&lt;p&gt;But my early Go code looked like 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;ProcessPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Get payment details&lt;/span&gt;
    &lt;span class="n"&gt;payment&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="c"&gt;// Which error? What happened?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Process the payment&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;paymentGateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="c"&gt;// Again, what went wrong?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Update payment status&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"processed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="c"&gt;// Did the payment go through? Is it in a bad state?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Functionally, this code worked. But it haunted me at night because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Error handling was minimal and provided no context&lt;/li&gt;
&lt;li&gt;There was no logging for debugging&lt;/li&gt;
&lt;li&gt;No consideration for partial failures&lt;/li&gt;
&lt;li&gt;No validation of inputs&lt;/li&gt;
&lt;li&gt;No testing for edge cases&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result? Support tickets on Saturday mornings. Mysterious payment failures. Hours spent on debugging sessions. And the constant anxiety that something might be failing silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Path to Trustworthy Code
&lt;/h2&gt;

&lt;p&gt;Everything changed when I joined a team at WF. My mentor there had a simple philosophy: "Write every line of code as if you'll be on vacation when it runs in production."&lt;/p&gt;

&lt;p&gt;This mindset shift transformed how I approached Go development. Here's what I learned, and what now lets me sleep well after committing code:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Errors Are Your Friends, Not Exceptions
&lt;/h3&gt;

&lt;p&gt;Go's error handling is verbose but powerful when used correctly. The secret is to treat errors as valuable information carriers, not just failure signals:&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;ProcessPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Get payment details&lt;/span&gt;
    &lt;span class="n"&gt;payment&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to retrieve payment %s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paymentID&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="c"&gt;// Validate before proceeding&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;validatePayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"payment validation failed for %s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paymentID&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="c"&gt;// Process the payment with context&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;paymentGateway&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Log additional details for debugging&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;WithFields&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;Fields&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"payment_id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paymentID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"amount"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"currency"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Currency&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;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Payment processing failed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gateway failed to process payment %s: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paymentID&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="c"&gt;// Success path is clearly logged too&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;WithField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"payment_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paymentID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Payment processed successfully"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference? When something goes wrong, I have rich context. The error messages tell a story, making debugging faster and easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Tests That Give You Confidence
&lt;/h3&gt;

&lt;p&gt;My earlier self wrote tests that proved the code worked in the happy path. My current self writes tests that prove the code won't break in production:&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;TestProcessPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Happy path test&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"successful payment processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Setup and assertions&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// What happens when things go wrong&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"database unavailable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Simulate DB failure&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"payment gateway timeout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Simulate slow payment gateway&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"invalid payment data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Test validation logic&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"partial failure - payment processed but status update fails"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Test recovery mechanisms&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;A comprehensive test suite is like insurance. It doesn't prevent all problems, but it significantly reduces the likelihood of common failures reaching production.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Graceful Degradation
&lt;/h3&gt;

&lt;p&gt;One key insight: not all failures are equal. The best Go code doesn't just handle errors; it gracefully degrades functionality:&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;GetUserRecommendations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userID&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;Recommendation&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="c"&gt;// Try to get personalized recommendations&lt;/span&gt;
    &lt;span class="n"&gt;recommendations&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;recommendationService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPersonalized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Log the error&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;WithError&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get personalized recommendations, falling back to popular items"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// Fall back to popular recommendations&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;recommendationService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPopular&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;recommendations&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;This pattern means your code tries its best to provide value, even when some components fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Monitoring and Observability Built-In
&lt;/h3&gt;

&lt;p&gt;Code I can trust doesn't just work well; it tells me how it's working:&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;ProcessOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="n"&gt;Order&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="c"&gt;// Start timing the operation&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Use defer to ensure metrics are always recorded&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObserveOrderProcessingTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncrementOrdersProcessed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="c"&gt;// Trace this operation for distributed tracing&lt;/span&gt;
    &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartSpanFromContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"process_order"&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;span&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Finish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Add helpful information to the trace&lt;/span&gt;
    &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"order_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customer_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomerID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Process the order with the traced context&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;orderProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Record error in metrics and trace&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncrementOrderErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogKV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error.message"&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;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"processing order %s failed: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&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;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When your code has built-in monitoring, you don't need to wonder if it's working correctly in production. You &lt;em&gt;know&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Life Example: The 3 AM Bug That Never Called
&lt;/h2&gt;

&lt;p&gt;Last year, we deployed a new feature to our payment system right before a long holiday weekend. The old me would have been anxious the entire time, but I wasn't worried at all.&lt;/p&gt;

&lt;p&gt;Sure enough, something unexpected happened: a third-party API we depended on changed their response format. But instead of a production outage, here's what happened:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Our validation caught the changed format and returned a clear error&lt;/li&gt;
&lt;li&gt;The circuit breaker we implemented prevented cascading failures&lt;/li&gt;
&lt;li&gt;The system fell back to a secondary processing method&lt;/li&gt;
&lt;li&gt;Our monitoring alerted the on-call engineer with the exact issue&lt;/li&gt;
&lt;li&gt;Detailed logs showed exactly where and how the format had changed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The on-call engineer fixed it with a simple config change—no emergency, no all-hands debugging session.&lt;/p&gt;

&lt;p&gt;The best part? I only found out about this when I read the incident report on Tuesday morning.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Write Go Code You Can Trust
&lt;/h2&gt;

&lt;p&gt;After a decade of writing Go, here's my checklist for code I can trust enough to disconnect completely from work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Handle errors with context&lt;/strong&gt;: Wrap errors, add information, make debugging easy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test failure modes&lt;/strong&gt;: Don't just test success cases; test what happens when things fail&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build in graceful degradation&lt;/strong&gt;: Design systems that bend rather than break&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make it observable&lt;/strong&gt;: Logging, metrics, and tracing are not afterthoughts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate early and thoroughly&lt;/strong&gt;: Catch bad inputs before they cause damage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document assumptions&lt;/strong&gt;: Clear documentation helps future you and your teammates&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The difference between Go code that keeps you up at night and Go code you can trust isn't about clever algorithms or advanced features. It's about care, attention to detail, and a mindset that prepares for the unexpected.&lt;/p&gt;

&lt;p&gt;When I interview Go developers now, I don't just look at how well they can write code that works. I look at how they handle the edge cases, how they think about failures, and whether their code would let them enjoy their weekends without worry.&lt;/p&gt;

&lt;p&gt;Because in the end, the best code isn't just functionally correct—it's trustworthy enough that you can commit it on Friday afternoon and genuinely disconnect until Monday morning.&lt;/p&gt;

&lt;p&gt;And for me, that peace of mind is worth every extra line of error handling, every additional test case, and every minute spent making my code more robust.&lt;/p&gt;

&lt;p&gt;So next time you're writing Go code, ask yourself: "Would I sleep well tonight if this ran in production after I left?" If the answer isn't a confident "yes," you have more work to do.&lt;/p&gt;

&lt;p&gt;Your future self—possibly on a beach somewhere without laptop access—will thank you.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>coding</category>
      <category>webdev</category>
    </item>
    <item>
      <title>ByteDance/Sonic: A Lightning-Fast JSON Library for Go</title>
      <dc:creator>Trung Duong</dc:creator>
      <pubDate>Tue, 04 Feb 2025 04:20:16 +0000</pubDate>
      <link>https://forem.com/trungdlp/bytedancesonic-a-lightning-fast-json-library-for-go-1931</link>
      <guid>https://forem.com/trungdlp/bytedancesonic-a-lightning-fast-json-library-for-go-1931</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"In the world of microservices, every millisecond counts. See how TikTok's engineering team revolutionized JSON processing in Go."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb5r59ha04xxus2b36qx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb5r59ha04xxus2b36qx.png" alt="JSON" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever deployed a Go service and watched your CPU spike when processing thousands of JSON requests? You're not alone. TikTok's engineers faced this exact challenge at a massive scale - billions of requests per day. Their solution? They created Sonic, a JSON library that's changing the game for Go developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The JSON Problem Every Go Developer Knows
&lt;/h2&gt;

&lt;p&gt;If you're a Go developer, you've probably used the standard &lt;code&gt;encoding/json&lt;/code&gt; package. It works, but let's be real - it's not the fastest kid on the block. If you're building modern web services or APIs, you're working with JSON every day - from REST APIs to configuration files. When TikTok's engineers found their services processing millions of JSON requests per second, even small performance improvements in JSON handling could make a huge difference in server costs and user experience.&lt;/p&gt;

&lt;p&gt;Let's look at a common scenario:&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;// Your typical JSON processing with standard library&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"name"`&lt;/span&gt;
    &lt;span class="n"&gt;Posts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="s"&gt;`json:"posts"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Processing this for millions of requests...&lt;/span&gt;
&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At small scale, this works fine. But when you're handling TikTok-scale traffic, those milliseconds add up to significant server costs and latency. That's exactly why ByteDance's team decided to tackle this challenge head-on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Speed Champion: Meet Sonic
&lt;/h2&gt;

&lt;p&gt;Let's look at some real numbers first. When working with a medium-sized JSON file (about 13KB):&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;// Processing user profile with posts and metadata&lt;/span&gt;
&lt;span class="n"&gt;Standard&lt;/span&gt; &lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;106&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;322&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nanoseconds&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Sonic&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;393&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;
&lt;span class="n"&gt;Memory&lt;/span&gt; &lt;span class="n"&gt;Usage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Standard&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="m"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;136&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="m"&gt;789&lt;/span&gt; &lt;span class="n"&gt;allocations&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Sonic&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;965&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;just&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="n"&gt;allocations&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/bytedance/sonic/blob/main/testdata/small.go" rel="noopener noreferrer"&gt;Small&lt;/a&gt; (400B, 11 keys, 3 layers)
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0sl259re9u93h70w818.png" alt="small benchmarks" width="800" height="303"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/bytedance/sonic/blob/main/testdata/twitter.json" rel="noopener noreferrer"&gt;Large&lt;/a&gt; (635KB, 10000+ key, 6 layers)
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfvqo7bwgd0ddk2aiqp1.png" alt="large benchmarks" width="800" height="289"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href="https://github.com/bytedance/sonic/blob/main/scripts/bench.sh" rel="noopener noreferrer"&gt;bench.sh&lt;/a&gt; for benchmark codes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Secret Sauce: Four Simple Tricks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Just-In-Time Compilation (JIT)
&lt;/h3&gt;

&lt;p&gt;Imagine you're a chef. Instead of following a generic recipe every time, you create a special, optimized recipe for each specific dish you make frequently. That's what JIT does!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular Go JSON library: Uses the same generic code for all JSON&lt;/li&gt;
&lt;li&gt;Sonic: Creates specialized code paths for your specific JSON structures&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. SIMD: Doing More Work at Once
&lt;/h3&gt;

&lt;p&gt;Think of SIMD like having multiple hands to do a task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular way: Sort cards one by one&lt;/li&gt;
&lt;li&gt;SIMD way: Sort multiple cards at once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sonic uses these "multiple hands" (SIMD instructions) to process JSON data in parallel, making everything faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Smart Memory Usage
&lt;/h3&gt;

&lt;p&gt;Here's a clever trick Sonic uses: When it finds a string in your JSON that doesn't have any special characters, it doesn't make a copy. Instead, it just points to the original string. It's like giving directions instead of drawing a new map!&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;// Example JSON&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"city"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"New York"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Standard library: Makes copies of "John" and "New York"&lt;/span&gt;
&lt;span class="c"&gt;// Sonic: Just references these strings if they're simple&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Optional Features = Better Speed
&lt;/h3&gt;

&lt;p&gt;Sonic makes some smart choices about what features to make optional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doesn't sort map keys by default (saves 10% processing time)&lt;/li&gt;
&lt;li&gt;Doesn't escape HTML by default (saves 15% processing time)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can still turn these features on if you need them, but by making them optional, Sonic stays fast for most common uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;p&gt;The design is easy to implement:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Aiming at the function-call overhead cost by the codec dynamic-assembly, &lt;strong&gt;&lt;code&gt;JIT&lt;/code&gt; tech is used to assemble opcodes (asm) corresponding to the schema at runtime&lt;/strong&gt;, which is finally cached into the off-heap memory in the form of Golang functions.&lt;/li&gt;
&lt;li&gt;For practical scenarios where big data and small data coexist, we &lt;strong&gt;use pre-conditional judgment&lt;/strong&gt; (string size, floating precision, etc.) &lt;strong&gt;to combine &lt;code&gt;SIMD&lt;/code&gt; with scalar instructions&lt;/strong&gt; to achieve the best adaptation.&lt;/li&gt;
&lt;li&gt;As for insufficiency in compiling optimization of go language, we decided to &lt;strong&gt;use &lt;code&gt;C/Clang&lt;/code&gt; to write and compile core computational functions&lt;/strong&gt;, and &lt;strong&gt;developed a set of &lt;a href="https://github.com/chenzhuoyu/asm2asm" rel="noopener noreferrer"&gt;asm2asm&lt;/a&gt; tools to translate the fully optimized x86 assembly into plan9&lt;/strong&gt; and finally load it into Golang runtime.&lt;/li&gt;
&lt;li&gt;Giving the big speed gap between parsing and skipping, the &lt;strong&gt;&lt;code&gt;lazy-load&lt;/code&gt; mechanism&lt;/strong&gt; is certainly used in our AST parser, but in &lt;strong&gt;a more adaptive and efficient way to reduce the overhead of multiple-key queries&lt;/strong&gt;.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2eu09g87hnywu1td9rwx.png" alt="design" width="800" height="506"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In detail,  we conducted some further optimization:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Since the native-asm functions cannot be inlined in Golang, we found that its cost even exceeded the improvement brought by the optimization of the C compiler. So we reimplemented a set of lightweight function-calls in JIT:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Global-function-table + static offset&lt;/code&gt; for calling instruction&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pass parameters using registers&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Sync.Map&lt;/code&gt; was used to cache the codecs at first, but for our &lt;strong&gt;quasi-static&lt;/strong&gt; (read far more than write), &lt;strong&gt;fewer elements&lt;/strong&gt; (usually no more than a few dozen) scenarios, its performance is not optimal, so we reimplement a high-performance and concurrent-safe cache with &lt;code&gt;open-addressing-hash + RCU&lt;/code&gt; tech.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/bytedance/sonic/blob/main/docs/INTRODUCTION.md#design" rel="noopener noreferrer"&gt;From Sonic Design&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Let's talk numbers that matter in the real world:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Memory Usage (for medium JSON):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standard Go: Uses about 49KB of memory with 789 allocations&lt;/li&gt;
&lt;li&gt;Sonic: Uses only about 12KB with just 4 allocations&lt;/li&gt;
&lt;li&gt;That's huge when you're processing millions of requests!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Practical Impact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster API responses&lt;/li&gt;
&lt;li&gt;Lower server costs&lt;/li&gt;
&lt;li&gt;Better user experience&lt;/li&gt;
&lt;li&gt;More requests handled per server&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Should You Switch to Sonic?
&lt;/h2&gt;

&lt;p&gt;Sonic might be great for you if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You process lots of JSON data&lt;/li&gt;
&lt;li&gt;Performance is important for your application&lt;/li&gt;
&lt;li&gt;You're working on AMD64 or ARM64 processors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It requires Go version 1.17 or higher&lt;/li&gt;
&lt;li&gt;It works on Linux, MacOS, and Windows&lt;/li&gt;
&lt;li&gt;Some features (like HTML escaping) need to be explicitly enabled if you need them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start Example
&lt;/h2&gt;

&lt;p&gt;Here's how simple it is to use Sonic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/bytedance/sonic"&lt;/span&gt;

&lt;span class="c"&gt;// Encoding&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;bytes&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;sonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Decoding&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sonic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Sonic shows us that even with something as common as JSON processing, there's still room for impressive improvements. By using modern CPU features (SIMD), smart compilation (JIT), and thoughtful design choices, it achieves remarkable performance gains over the standard library.&lt;/p&gt;

&lt;p&gt;Remember: In software development, it's not just about making things work - sometimes, making them work faster can open up new possibilities for what your applications can achieve!&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;Want to dive deeper? Here are some great resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/bytedance/sonic" rel="noopener noreferrer"&gt;Sonic GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bytedance/sonic/blob/main/docs/INTRODUCTION.md" rel="noopener noreferrer"&gt;Technical Introduction Document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bytedance/sonic/blob/main/docs/INTRODUCTION.md#benchmarks" rel="noopener noreferrer"&gt;Sonic Benchmark Details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data" rel="noopener noreferrer"&gt;SIMD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Just-in-time_compilation" rel="noopener noreferrer"&gt;JIT compilation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://victoriametrics.com/blog/go-sync-map/" rel="noopener noreferrer"&gt;sync.Map&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;What do you think about Sonic? Have you tried using it in your Go projects? Let me know in the comments below!&lt;/p&gt;

</description>
      <category>go</category>
      <category>backend</category>
      <category>json</category>
      <category>restapi</category>
    </item>
  </channel>
</rss>
