<?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: Richard Ochola</title>
    <description>The latest articles on DEV Community by Richard Ochola (@ochola).</description>
    <link>https://dev.to/ochola</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%2F3732820%2F8b2f74e4-0bc9-4355-a739-5f3e75035dd7.jpeg</url>
      <title>DEV Community: Richard Ochola</title>
      <link>https://dev.to/ochola</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ochola"/>
    <language>en</language>
    <item>
      <title>Mistakes every Go beginner makes. Part 1 : Time Complexity Issues</title>
      <dc:creator>Richard Ochola</dc:creator>
      <pubDate>Tue, 03 Feb 2026 11:43:15 +0000</pubDate>
      <link>https://dev.to/ochola/mistakes-every-go-beginner-makes-part-1-time-complexity-issues-4ao5</link>
      <guid>https://dev.to/ochola/mistakes-every-go-beginner-makes-part-1-time-complexity-issues-4ao5</guid>
      <description>&lt;p&gt;When you start learning Go, the syntax feels clean and the speed feels amazing. But there is a trap many beginners fall into: writing code that works perfectly for small tasks but crawls to a halt when the data gets bigger.&lt;/p&gt;

&lt;p&gt;Recently, I was working on an &lt;strong&gt;ASCII Art Generator&lt;/strong&gt;. The logic was simple: take a string, find the corresponding ASCII characters in a template file, and print them out. However, I noticed that as my input text got longer, the program started lagging.&lt;/p&gt;

&lt;p&gt;The culprit? &lt;strong&gt;How I was collecting my results.&lt;/strong&gt; Let's look at the two "silent" performance killers I found in my own code.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The String Concatenation Trap
&lt;/h2&gt;

&lt;p&gt;In my project, I had a function to build the final output string. I was using the &lt;code&gt;+=&lt;/code&gt; operator to join every line together.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Before" Code (Slow):
&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;func&lt;/span&gt; &lt;span class="n"&gt;OutputCharacters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&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;charmap&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;rune&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="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;""&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;line&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;BuildASCII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charmap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;res&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;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="c"&gt;// The Hidden Performance Killer&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;res&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Technical "Why"
&lt;/h3&gt;

&lt;p&gt;In Go, &lt;strong&gt;strings are immutable&lt;/strong&gt;. This means once a string is created in memory, it can never be changed.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;res += line&lt;/code&gt;, Go doesn't just "tack" the new text onto the end. Instead, it performs a costly cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It allocates a &lt;strong&gt;brand new memory block&lt;/strong&gt; large enough for the old string + the new line.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;copies&lt;/strong&gt; every single byte from the old string into the new one.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;copies&lt;/strong&gt; the new line into the new memory.&lt;/li&gt;
&lt;li&gt;It throws away the old string for the Garbage Collector to clean up.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As your loop grows, you are copying the same data over and over again. This creates a *&lt;em&gt;Time Complexity of *&lt;/em&gt;. If you have 1,000 lines, you aren't just doing 1,000 operations; you're performing millions of byte copies!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: &lt;code&gt;strings.Builder&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Go provides &lt;code&gt;strings.Builder&lt;/code&gt;, which uses a mutable byte slice internally. It grows smarter (usually doubling in size) so it doesn't have to copy everything every time.&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;OutputCharacters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&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;charmap&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;rune&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;var&lt;/span&gt; &lt;span class="n"&gt;builder&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;Builder&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;BuildASCII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charmap&lt;/span&gt;&lt;span class="p"&gt;)&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;line&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;lines&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&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;builder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteByte&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="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;builder&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="c"&gt;// Final string is created only ONCE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. The Unallocated Slice Issue
&lt;/h2&gt;

&lt;p&gt;Inside my &lt;code&gt;BuildASCII&lt;/code&gt; function, I was creating a slice of strings to hold the art, but I was initializing it as an empty slice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem:
&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;res&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="c"&gt;// Length: 0, Capacity: 0&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A slice in Go is backed by an &lt;strong&gt;underlying array&lt;/strong&gt;. When you &lt;code&gt;append&lt;/code&gt; to a slice that is full, Go has to "move house":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It finds a new, larger spot in memory.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;copies&lt;/strong&gt; all current elements to the new spot.&lt;/li&gt;
&lt;li&gt;It updates the slice pointer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my ASCII project, I knew that every word in the input would result in exactly 8 lines of ASCII art. By not telling Go this, I was forcing the program to stop and "move house" (reallocate) multiple times as the list grew.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Pre-allocation with &lt;code&gt;make&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you can calculate or even estimate the size, you should pre-allocate the capacity. This "reserves" the memory upfront.&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;BuildASCII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&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;charmap&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;rune&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="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// We know the exact size: 8 lines per input word&lt;/span&gt;
    &lt;span class="n"&gt;totalExpected&lt;/span&gt; &lt;span class="o"&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;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
    &lt;span class="n"&gt;res&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;string&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;totalExpected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Length 0, but Capacity is set!&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;word&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;input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// ... build lines ...&lt;/span&gt;
        &lt;span class="n"&gt;res&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;res&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="c"&gt;// Zero reallocations happen now!&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;res&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;When you're a beginner, "making it work" is the priority. But as you grow, "making it efficient" becomes the goal. By understanding how Go handles memory, you can prevent your programs from slowing down as they scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you run into these "slow loops" before? What other beginner traps should I cover in Part 2? Let me know below!&lt;/strong&gt; &lt;/p&gt;

</description>
      <category>programming</category>
      <category>devops</category>
      <category>beginners</category>
      <category>go</category>
    </item>
  </channel>
</rss>
