<?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: perez odiyo</title>
    <description>The latest articles on DEV Community by perez odiyo (@perezodiyo).</description>
    <link>https://dev.to/perezodiyo</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3945422%2F496b7531-ce1b-4b5c-afb1-4e3e5a34bd5d.png</url>
      <title>DEV Community: perez odiyo</title>
      <link>https://dev.to/perezodiyo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/perezodiyo"/>
    <language>en</language>
    <item>
      <title>Arrays vs Slices in Go: The Concept Every Beginner Struggles With (Until It Finally Clicks)</title>
      <dc:creator>perez odiyo</dc:creator>
      <pubDate>Wed, 22 Jul 2026 07:20:41 +0000</pubDate>
      <link>https://dev.to/perezodiyo/-arrays-vs-slices-in-go-the-concept-every-beginner-struggles-with-until-it-finally-clicks-37mo</link>
      <guid>https://dev.to/perezodiyo/-arrays-vs-slices-in-go-the-concept-every-beginner-struggles-with-until-it-finally-clicks-37mo</guid>
      <description>&lt;p&gt;There are a handful of concepts every Go beginner wrestles with.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pointers.&lt;/li&gt;
&lt;li&gt;Interfaces.&lt;/li&gt;
&lt;li&gt;Goroutines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And somewhere near the top of that list sits a deceptively simple pair:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arrays and slices.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I first started learning Go, I honestly thought they were the same thing.&lt;/p&gt;

&lt;p&gt;Both stored multiple values.&lt;/p&gt;

&lt;p&gt;Both used square brackets.&lt;/p&gt;

&lt;p&gt;Both let me access elements by index.&lt;/p&gt;

&lt;p&gt;So naturally, I asked myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why does Go have two data structures that seem to do exactly the same thing?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Like many beginners, I searched for the answer.&lt;/p&gt;

&lt;p&gt;Every explanation sounded something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arrays have a fixed size.&lt;/li&gt;
&lt;li&gt;Slices are dynamic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically...&lt;/p&gt;

&lt;p&gt;That's correct.&lt;/p&gt;

&lt;p&gt;But it wasn't helpful.&lt;/p&gt;

&lt;p&gt;Knowing &lt;strong&gt;what&lt;/strong&gt; they are isn't the same as understanding &lt;strong&gt;why&lt;/strong&gt; they exist.&lt;/p&gt;

&lt;p&gt;The real breakthrough came when I stopped thinking about arrays and slices as two competing data structures and started seeing their relationship.&lt;/p&gt;

&lt;p&gt;Imagine a bookshelf.&lt;/p&gt;

&lt;p&gt;The bookshelf holds the books.&lt;/p&gt;

&lt;p&gt;It owns them.&lt;/p&gt;

&lt;p&gt;Now imagine placing a transparent picture frame in front of just a few books.&lt;/p&gt;

&lt;p&gt;The frame doesn't move the books.&lt;/p&gt;

&lt;p&gt;It doesn't copy them.&lt;/p&gt;

&lt;p&gt;It simply gives you a different view of what's already there.&lt;/p&gt;

&lt;p&gt;That's exactly what a slice is.&lt;/p&gt;

&lt;p&gt;Once that idea clicked, suddenly everything else made sense.&lt;/p&gt;

&lt;p&gt;Why changing a slice sometimes changes an array.&lt;/p&gt;

&lt;p&gt;Why &lt;code&gt;append()&lt;/code&gt; sometimes behaves strangely.&lt;/p&gt;

&lt;p&gt;Why Go developers almost always use slices instead of arrays.&lt;/p&gt;

&lt;p&gt;And why arrays still exist in the language at all.&lt;/p&gt;

&lt;p&gt;By the end of this article, you'll stop memorizing definitions and start thinking the way Go does.&lt;/p&gt;

&lt;p&gt;Let's build that intuition together.&lt;/p&gt;




&lt;h2&gt;
  
  
  Arrays: The Bookshelf
&lt;/h2&gt;

&lt;p&gt;Let's start with the bookshelf itself.&lt;/p&gt;

&lt;p&gt;Imagine you've just built a wooden bookshelf with &lt;strong&gt;five shelves&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not four.&lt;/p&gt;

&lt;p&gt;Not six.&lt;/p&gt;

&lt;p&gt;Exactly five.&lt;/p&gt;

&lt;p&gt;Once it's built, changing the number of shelves isn't as simple as snapping another one on.&lt;/p&gt;

&lt;p&gt;You'd have to build a completely new bookshelf.&lt;/p&gt;

&lt;p&gt;That's exactly how an array works.&lt;/p&gt;

&lt;p&gt;An array is a collection of values with a size that's decided the moment it's is created.&lt;/p&gt;

&lt;p&gt;Here's an example.&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;5&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;"Go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Rust"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"JavaScript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"TypeScript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Python"&lt;/span&gt;&lt;span class="p"&gt;,&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;languages&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Go Rust JavaScript TypeScript Python]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing surprising yet.&lt;/p&gt;

&lt;p&gt;But look closely at the declaration.&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="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most beginners read that as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"An array containing five strings."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go reads it differently.&lt;/p&gt;

&lt;p&gt;Go sees &lt;strong&gt;&lt;code&gt;[5]string&lt;/code&gt; as the type itself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That means these are completely different types.&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="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though they both store strings.&lt;/p&gt;

&lt;p&gt;The number isn't just information.&lt;/p&gt;

&lt;p&gt;It's part of the type.&lt;/p&gt;

&lt;p&gt;That tiny detail explains why arrays behave the way they do.&lt;/p&gt;

&lt;p&gt;Go already knows exactly how much memory to reserve before your program even runs.&lt;/p&gt;

&lt;p&gt;It's like buying a bookshelf with exactly five compartments.&lt;/p&gt;

&lt;p&gt;The carpenter isn't expecting you to ask for a sixth shelf later.&lt;/p&gt;

&lt;p&gt;The design is already finished.&lt;/p&gt;




&lt;h3&gt;
  
  
  Arrays Own Their Data
&lt;/h3&gt;

&lt;p&gt;Here's another idea that confused me when I started learning Go.&lt;/p&gt;

&lt;p&gt;Suppose you buy another identical bookshelf.&lt;/p&gt;

&lt;p&gt;Then you copy every single book from the first shelf onto the second one.&lt;/p&gt;

&lt;p&gt;Now you have &lt;strong&gt;two completely separate bookshelves.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Changing one won't affect the other.&lt;/p&gt;

&lt;p&gt;Arrays work exactly like that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original

+------+------+------+------+------+
| Go | Rust | JS | TS | Py |
+------+------+------+------+------+

Copy

+------+------+------+------+------+
| Go | Rust | JS | TS | Py |
+------+------+------+------+------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see it in Go.&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;scores&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;78&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;copyScores&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;

&lt;span class="n"&gt;copyScores&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="m"&gt;100&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copyScores&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[85 92 78]

[100 92 78]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changing &lt;code&gt;copyScores&lt;/code&gt; didn't affect &lt;code&gt;scores&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because Go copied the entire array.&lt;/p&gt;

&lt;p&gt;Arrays &lt;strong&gt;own&lt;/strong&gt; their data.&lt;/p&gt;

&lt;p&gt;Whenever you assign an array to another variable or pass it into a function, Go creates a brand-new copy.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;value semantics&lt;/strong&gt;, but don't worry about memorizing that phrase.&lt;/p&gt;

&lt;p&gt;Just remember this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Arrays own their bookshelf.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every copy gets its own bookshelf.&lt;/p&gt;

&lt;p&gt;No sharing.&lt;/p&gt;

&lt;p&gt;No surprises.&lt;/p&gt;

&lt;p&gt;And that's exactly where slices enter the story...&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Golang Beginner Mistakes #4: Learning Interfaces Changed How I Write Go</title>
      <dc:creator>perez odiyo</dc:creator>
      <pubDate>Mon, 20 Jul 2026 07:32:43 +0000</pubDate>
      <link>https://dev.to/perezodiyo/-golang-beginner-mistakes-5-learning-interfaces-changed-how-i-write-go-586c</link>
      <guid>https://dev.to/perezodiyo/-golang-beginner-mistakes-5-learning-interfaces-changed-how-i-write-go-586c</guid>
      <description>&lt;p&gt;For the longest time, I avoided interfaces.&lt;/p&gt;

&lt;p&gt;Not because I thought they were useless.&lt;/p&gt;

&lt;p&gt;But because every explanation I came across felt like a computer science lecture.&lt;/p&gt;

&lt;p&gt;People kept saying things like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Program to interfaces."&lt;/p&gt;

&lt;p&gt;"Accept interfaces, return structs."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I understood the words.&lt;/p&gt;

&lt;p&gt;I just didn't understand &lt;strong&gt;why&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why would I need an interface when my structs and functions were working just fine?&lt;/p&gt;

&lt;p&gt;Then I ran into a problem that structs alone couldn't solve.&lt;/p&gt;

&lt;p&gt;That's when interfaces stopped feeling like theory and started feeling like one of the most practical features in Go.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Story: Dog, Cat, and a Better Way
&lt;/h2&gt;

&lt;p&gt;I started with a dog.&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;type&lt;/span&gt; &lt;span class="n"&gt;Dog&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="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;d&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MakeSound&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;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" says Woof!"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then came the cat.&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;type&lt;/span&gt; &lt;span class="n"&gt;Cat&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="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;c&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MakeSound&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" says Meow!"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything looked fine.&lt;/p&gt;

&lt;p&gt;Until I wanted one function that could make &lt;strong&gt;any&lt;/strong&gt; animal speak.&lt;/p&gt;

&lt;p&gt;My first thought wasn't "interface."&lt;/p&gt;

&lt;p&gt;It was...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"There has to be a better way than writing one function for every animal."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I almost started writing&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;PrintDogSound&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;PrintCatSound&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;PrintCowSound&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;PrintBirdSound&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That didn't feel right.&lt;/p&gt;

&lt;p&gt;There had to be a cleaner solution.&lt;/p&gt;

&lt;p&gt;There was.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Beginner Mistake
&lt;/h2&gt;

&lt;p&gt;Many Go beginners postpone learning interfaces.&lt;/p&gt;

&lt;p&gt;I certainly did.&lt;/p&gt;

&lt;p&gt;The word sounds like something from a computer science lecture.&lt;/p&gt;

&lt;p&gt;In reality, it's one of the simplest ideas in Go.&lt;/p&gt;

&lt;p&gt;The trick is realizing that interfaces aren't about &lt;strong&gt;data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They're about &lt;strong&gt;behavior&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is an Interface?
&lt;/h2&gt;

&lt;p&gt;A struct answers one question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is this thing?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;Dog&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A dog has a name.&lt;/p&gt;

&lt;p&gt;That's data.&lt;/p&gt;

&lt;p&gt;An interface answers a different question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What can this thing do?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;Speaker&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;MakeSound&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something.&lt;/p&gt;

&lt;p&gt;The interface doesn't mention dogs.&lt;/p&gt;

&lt;p&gt;Or cats.&lt;/p&gt;

&lt;p&gt;Or humans.&lt;/p&gt;

&lt;p&gt;It only says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If you can make a sound, you're welcome here."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the magic.&lt;/p&gt;




&lt;h2&gt;
  
  
  No &lt;code&gt;implements&lt;/code&gt; Keyword?
&lt;/h2&gt;

&lt;p&gt;If you're coming from Java or C#, this part feels strange.&lt;/p&gt;

&lt;p&gt;Normally you'd write something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Speaker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go doesn't do that.&lt;/p&gt;

&lt;p&gt;Instead, it quietly checks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Does this type have the required method?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If yes...&lt;/p&gt;

&lt;p&gt;Congratulations.&lt;/p&gt;

&lt;p&gt;It already satisfies the interface.&lt;/p&gt;

&lt;p&gt;No keyword.&lt;/p&gt;

&lt;p&gt;No inheritance.&lt;/p&gt;

&lt;p&gt;No registration.&lt;/p&gt;

&lt;p&gt;Just behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;Let's add more types.&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;type&lt;/span&gt; &lt;span class="n"&gt;Speaker&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;MakeSound&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;Dog&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="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;d&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MakeSound&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;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" says Woof!"&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;Cat&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="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;c&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MakeSound&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" says Meow!"&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;Human&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="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;h&lt;/span&gt; &lt;span class="n"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MakeSound&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;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" says Hello!"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now watch 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;Announce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Speaker&lt;/span&gt;&lt;span class="p"&gt;)&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeSound&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Announce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dog&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="s"&gt;"Rex"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;Announce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Cat&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="s"&gt;"Milo"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;Announce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Human&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="s"&gt;"Perez"&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 beautiful part is that &lt;code&gt;Announce&lt;/code&gt; never asks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are you a Dog?&lt;/li&gt;
&lt;li&gt;Are you a Cat?&lt;/li&gt;
&lt;li&gt;Are you a Human?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It only asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Can you make a sound?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is yes...&lt;/p&gt;

&lt;p&gt;The function is happy.&lt;/p&gt;

&lt;p&gt;That's the moment interfaces finally clicked for me.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Beginner Mistake #1: Creating Interfaces Too Early
&lt;/h2&gt;

&lt;p&gt;Once interfaces make sense, beginners often swing too far in the other direction.&lt;/p&gt;

&lt;p&gt;Suddenly everything gets an interface.&lt;/p&gt;

&lt;p&gt;Even when there's only one implementation.&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;type&lt;/span&gt; &lt;span class="n"&gt;UserRepository&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GetUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;User&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only have one repository...&lt;/p&gt;

&lt;p&gt;You probably don't need the interface yet.&lt;/p&gt;

&lt;p&gt;A popular Go saying is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Accept interfaces. Return structs.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another one you'll hear often is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Define interfaces where they're used, not where they're implemented.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Start simple.&lt;/p&gt;

&lt;p&gt;Add interfaces when they solve a real problem.&lt;/p&gt;

&lt;p&gt;Not before.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Beginner Mistake #2: Using &lt;code&gt;any&lt;/code&gt; for Everything
&lt;/h2&gt;

&lt;p&gt;Some beginners discover&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;any&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and think they've found the ultimate shortcut.&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;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&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;Sure...&lt;/p&gt;

&lt;p&gt;It accepts everything.&lt;/p&gt;

&lt;p&gt;But it also throws away type safety.&lt;/p&gt;

&lt;p&gt;Instead of saying&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I accept anything."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What behavior do I actually need?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's usually an interface.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Examples You'll See Every Day
&lt;/h2&gt;

&lt;p&gt;Once interfaces click, you'll notice they're everywhere.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;io.Reader&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;io.Writer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http.Handler&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Database repositories&lt;/li&gt;
&lt;li&gt;Payment gateways&lt;/li&gt;
&lt;li&gt;Logging libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They all follow the same idea.&lt;/p&gt;

&lt;p&gt;Describe behavior.&lt;/p&gt;

&lt;p&gt;Not implementation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Struct vs Interface
&lt;/h2&gt;

&lt;p&gt;Whenever I'm unsure, I ask myself one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Am I describing data... or behavior?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If it's data...&lt;/p&gt;

&lt;p&gt;Use a struct.&lt;/p&gt;

&lt;p&gt;If it's behavior...&lt;/p&gt;

&lt;p&gt;Use an interface.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Interface?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Multiple types share behavior&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Only one implementation&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modeling data&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want loose coupling&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Future implementations expected&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Mental Model That Finally Stuck
&lt;/h2&gt;

&lt;p&gt;Forget complicated definitions.&lt;/p&gt;

&lt;p&gt;Just remember this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Struct = What is it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interface = What can it do?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Structs describe &lt;strong&gt;things&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Interfaces describe &lt;strong&gt;capabilities&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That distinction is what makes Go code so flexible without becoming complicated.&lt;/p&gt;




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

&lt;p&gt;One thing I love about Go is that it encourages simple designs.&lt;/p&gt;

&lt;p&gt;You don't start with giant inheritance trees.&lt;/p&gt;

&lt;p&gt;You don't spend hours designing interfaces "just in case."&lt;/p&gt;

&lt;p&gt;You build concrete types.&lt;/p&gt;

&lt;p&gt;Then, when multiple types share behavior...&lt;/p&gt;

&lt;p&gt;You introduce an interface.&lt;/p&gt;

&lt;p&gt;Go doesn't care what something &lt;strong&gt;is&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It cares what something &lt;strong&gt;can do&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That tiny mindset shift completely changed how I write Go.&lt;/p&gt;




&lt;h2&gt;
  
  
  Over to You
&lt;/h2&gt;

&lt;p&gt;What Go concept took you the longest to understand?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interfaces?&lt;/li&gt;
&lt;li&gt;Pointers?&lt;/li&gt;
&lt;li&gt;Slices?&lt;/li&gt;
&lt;li&gt;Goroutines?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd love to hear your story in the comments.&lt;/p&gt;

&lt;p&gt;If you enjoyed this article, consider following the &lt;strong&gt;Golang Beginner Mistakes&lt;/strong&gt; series, where we break down the kinds of mistakes almost every new Go developer makes—and how to avoid them.&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Golang Beginner Mistakes: If You Know Every Field, You Probably Don't Need a Map</title>
      <dc:creator>perez odiyo</dc:creator>
      <pubDate>Mon, 20 Jul 2026 07:03:12 +0000</pubDate>
      <link>https://dev.to/perezodiyo/-golang-beginner-mistakes-if-you-know-every-field-you-probably-dont-need-a-map-olj</link>
      <guid>https://dev.to/perezodiyo/-golang-beginner-mistakes-if-you-know-every-field-you-probably-dont-need-a-map-olj</guid>
      <description>&lt;p&gt;When I first started learning Go, I discovered &lt;code&gt;struct&lt;/code&gt;s before I discovered &lt;code&gt;map&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;So naturally...&lt;/p&gt;

&lt;p&gt;Everything became a struct.&lt;/p&gt;

&lt;p&gt;Need a user?&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;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="n"&gt;Email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easy.&lt;/p&gt;

&lt;p&gt;Need application settings?&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;type&lt;/span&gt; &lt;span class="n"&gt;Settings&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;Theme&lt;/span&gt;         &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Notifications&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still easy.&lt;/p&gt;

&lt;p&gt;Need categories users can create themselves?&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;I still made a struct.&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;type&lt;/span&gt; &lt;span class="n"&gt;Categories&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;Fitness&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Reading&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Coding&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looked fine until someone wanted to add &lt;strong&gt;"Meditation."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then another user wanted &lt;strong&gt;"Gaming."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then another wanted &lt;strong&gt;"Cooking."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's when it hit me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structs aren't meant to grow while your program is running.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I was using the wrong tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a struct actually is
&lt;/h2&gt;

&lt;p&gt;A beginner usually hears:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A struct groups related data."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's true.&lt;/p&gt;

&lt;p&gt;But it misses the important part.&lt;/p&gt;

&lt;p&gt;A better definition is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A struct describes something whose shape is already known.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, every user in your application has the same fields.&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;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="n"&gt;Email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You already know those fields before writing the program.&lt;/p&gt;

&lt;p&gt;That's why a struct exists.&lt;/p&gt;

&lt;p&gt;Think of it as a blueprint.&lt;/p&gt;

&lt;p&gt;Every house built from the same blueprint has the same rooms.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a map actually is
&lt;/h2&gt;

&lt;p&gt;A map is completely different.&lt;/p&gt;

&lt;p&gt;A map doesn't care what keys you'll use tomorrow.&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;prices&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;float64&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"apple"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.50&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;Later...&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;prices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"banana"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0.30&lt;/span&gt;
&lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"mango"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1.20&lt;/span&gt;
&lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"orange"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0.75&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No problem.&lt;/p&gt;

&lt;p&gt;Maps are designed for data whose &lt;strong&gt;keys are discovered at runtime.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The question that changed how I write Go
&lt;/h2&gt;

&lt;p&gt;Nowadays, before writing any type, I ask myself one question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do I already know every field this data will have?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is &lt;strong&gt;yes&lt;/strong&gt;, I create a struct.&lt;/p&gt;

&lt;p&gt;If the answer is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Well...the user decides."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It depends on the API."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It depends on the environment."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I immediately reach for a map.&lt;/p&gt;

&lt;p&gt;That one question has saved me countless rewrites.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Beginner Mistake #1: Treating dynamic data like fixed data
&lt;/h2&gt;

&lt;p&gt;Imagine you're storing HTTP headers.&lt;/p&gt;

&lt;p&gt;A beginner might write 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;type&lt;/span&gt; &lt;span class="n"&gt;Headers&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;ContentType&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Authorization&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;UserAgent&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks reasonable...&lt;/p&gt;

&lt;p&gt;Until a request contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;X-Request-ID&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Forwarded-For&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Or some completely custom header.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now your program needs another field.&lt;/p&gt;

&lt;p&gt;And another.&lt;/p&gt;

&lt;p&gt;And another.&lt;/p&gt;

&lt;p&gt;Instead, use a 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="n"&gt;headers&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;"Content-Type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"application/json"&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;Now any header can exist without changing your code.&lt;/p&gt;

&lt;p&gt;That's exactly what maps were made for.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Beginner Mistake #2: Using maps because they feel flexible
&lt;/h2&gt;

&lt;p&gt;Then comes the opposite mistake.&lt;/p&gt;

&lt;p&gt;You discover maps.&lt;/p&gt;

&lt;p&gt;They're cool.&lt;/p&gt;

&lt;p&gt;They're flexible.&lt;/p&gt;

&lt;p&gt;So suddenly everything becomes&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;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;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even users.&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;user&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="k"&gt;interface&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;"Perez"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;22&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 works.&lt;/p&gt;

&lt;p&gt;But you've thrown away one of Go's biggest strengths.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type safety.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This typo compiles.&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"nmae"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the spelling?&lt;/p&gt;

&lt;p&gt;The compiler doesn't.&lt;/p&gt;

&lt;p&gt;It happily runs your program.&lt;/p&gt;

&lt;p&gt;Now compare that with&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;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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nmae&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go immediately says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Nope."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compilation fails.&lt;/p&gt;

&lt;p&gt;That's exactly what you want.&lt;/p&gt;

&lt;p&gt;Let the compiler catch mistakes before your users do.&lt;/p&gt;




&lt;h2&gt;
  
  
  Structs and Maps Are Teammates, Not Enemies
&lt;/h2&gt;

&lt;p&gt;One thing took me embarrassingly long to realize.&lt;/p&gt;

&lt;p&gt;Structs and maps aren't competing.&lt;/p&gt;

&lt;p&gt;They're usually used together.&lt;/p&gt;

&lt;p&gt;A very common pattern is&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;type&lt;/span&gt; &lt;span class="n"&gt;Product&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="n"&gt;Price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;inventory&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="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what's happening.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Product&lt;/strong&gt; has a known shape.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;inventory&lt;/strong&gt; doesn't know how many products exist.&lt;/p&gt;

&lt;p&gt;One models an object.&lt;/p&gt;

&lt;p&gt;The other stores a growing collection of those objects.&lt;/p&gt;

&lt;p&gt;You'll see this pattern everywhere.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User sessions&lt;/li&gt;
&lt;li&gt;Product inventories&lt;/li&gt;
&lt;li&gt;Cache systems&lt;/li&gt;
&lt;li&gt;Feature flags&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;Backend services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you notice it, you can't unsee it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Struct vs Map: A Quick Decision Guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Struct&lt;/th&gt;
&lt;th&gt;Map&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Known fields&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unknown keys&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type safety&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic user input&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-world objects&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fast lookups by key&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  My Rule of Thumb
&lt;/h2&gt;

&lt;p&gt;Whenever I'm unsure, I ask myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Can I confidently write every field name before running the program?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If yes...&lt;/p&gt;

&lt;p&gt;➡️ Use a &lt;strong&gt;struct&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If no...&lt;/p&gt;

&lt;p&gt;➡️ Use a &lt;strong&gt;map&lt;/strong&gt;.&lt;/p&gt;

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




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

&lt;p&gt;One of my favorite things about Go is that it gives you only a handful of data structures.&lt;/p&gt;

&lt;p&gt;That means learning &lt;strong&gt;when&lt;/strong&gt; to use them matters more than memorizing &lt;strong&gt;how&lt;/strong&gt; to use them.&lt;/p&gt;

&lt;p&gt;I spent weeks treating every problem like a struct.&lt;/p&gt;

&lt;p&gt;Then I spent weeks treating every problem like a map.&lt;/p&gt;

&lt;p&gt;The sweet spot was realizing they solve completely different problems.&lt;/p&gt;

&lt;p&gt;A struct answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What is this thing?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A map answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"How do I find this thing?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once that clicked, my Go code became much simpler.&lt;/p&gt;




&lt;h2&gt;
  
  
  Over to You
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What beginner Go mistake took you the longest to understand?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear it in the comments. Chances are, someone else is struggling with the exact same thing.&lt;/p&gt;

&lt;p&gt;If you enjoyed this article, consider following the &lt;strong&gt;Golang Beginner Mistakes&lt;/strong&gt; series, where we break down the kinds of mistakes almost every new Go developer makes—and how to avoid them.&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Go Beginner Mistake #2: Why `time.Now().Format("YYYY-MM-DD")` Doesn't Work in Go</title>
      <dc:creator>perez odiyo</dc:creator>
      <pubDate>Sat, 06 Jun 2026 16:24:40 +0000</pubDate>
      <link>https://dev.to/perezodiyo/-go-beginner-mistake-2-why-timenowformatyyyy-mm-dd-doesnt-work-in-go-3j22</link>
      <guid>https://dev.to/perezodiyo/-go-beginner-mistake-2-why-timenowformatyyyy-mm-dd-doesnt-work-in-go-3j22</guid>
      <description>&lt;p&gt;&lt;em&gt;Dearest learner&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope this post finds you well.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you're here because &lt;code&gt;time.Now().Format("YYYY-MM-DD")&lt;/code&gt; isn't doing what you expected, pull up a chair. I spent an embarrassing amount of time staring at that exact problem, and today I'd like to save you the trouble.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  First, Some Embarrassing Context
&lt;/h2&gt;

&lt;p&gt;If you read my last post, you already know I was building a Net-Cat project in Go and got burned by &lt;code&gt;log.Println()&lt;/code&gt; silently adding its own timestamp to my output. Fun times.&lt;/p&gt;

&lt;p&gt;Well — I hadn't even gotten to that bug yet. Before I ran into the &lt;code&gt;log&lt;/code&gt; problem, I was still fighting a more basic battle: &lt;strong&gt;just getting a timestamp to print correctly in the first place.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is that story.&lt;/p&gt;




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

&lt;p&gt;I come from a JavaScript background. In JS, formatting a date looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// JavaScript&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 2025-01-15T14:32:05.000Z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in Python, it's something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# 2025-01-15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the pattern? Both use &lt;strong&gt;placeholder tokens&lt;/strong&gt;. &lt;code&gt;YYYY&lt;/code&gt; means "put the 4-digit year here." &lt;code&gt;MM&lt;/code&gt; means "put the month here." &lt;code&gt;%d&lt;/code&gt; means "put the day here." They're basically fill-in-the-blank templates where each token represents a concept.&lt;/p&gt;

&lt;p&gt;So when I opened a Go file and typed this, it felt completely natural:&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;// What I tried first (very wrong)&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;Println&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;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YYYY-MM-DD"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hit run.&lt;/p&gt;

&lt;p&gt;The output was: &lt;code&gt;YYYY-MM-DD&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Just... the string. Printed back at me, unchanged. No date. No numbers. Nothing.&lt;/p&gt;

&lt;p&gt;I sat there for a second. Then I tried &lt;code&gt;"yyyy-mm-dd"&lt;/code&gt;. Same thing. Then &lt;code&gt;"%Y-%m-%d"&lt;/code&gt; like Python. Same thing. Go was just printing whatever I typed, completely unbothered.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Thing Nobody Warned Me About
&lt;/h2&gt;

&lt;p&gt;Here's what Go actually does, and I wish someone had just said this to me directly on day one:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go doesn't use placeholder tokens. It uses a real, specific reference date.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That reference date is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mon Jan 2 15:04:05 MST 2006
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or written out in numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01/02 03:04:05PM '06 -0700
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You use &lt;em&gt;that exact date&lt;/em&gt; — in whatever arrangement you want — as your format string. Go looks at your string, recognises the pieces of that reference date inside it, and replaces them with today's values.&lt;/p&gt;

&lt;p&gt;So instead of &lt;code&gt;"YYYY-MM-DD"&lt;/code&gt;, you write:&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&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;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c"&gt;// Output: 2025-01-15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;2006&lt;/code&gt; is the year. That &lt;code&gt;01&lt;/code&gt; is the month. That &lt;code&gt;02&lt;/code&gt; is the day. Not because those are magic tokens — but because &lt;strong&gt;January 2nd, 2006&lt;/strong&gt; is the reference date Go was built around.&lt;/p&gt;

&lt;p&gt;The first time I read that, I genuinely thought the documentation was trolling me.&lt;/p&gt;




&lt;h2&gt;
  
  
  And Then I Used the Wrong Date
&lt;/h2&gt;

&lt;p&gt;Even after I understood the concept — &lt;em&gt;"use a real reference date"&lt;/em&gt; — I still got burned. Because I thought: okay, any date will do. I need year-month-day, so I'll just write a date in that order.&lt;/p&gt;

&lt;p&gt;I typed &lt;code&gt;"2020-02-12"&lt;/code&gt; and felt confident.&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&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;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2020-02-12"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c"&gt;// I expected: 2025-01-15&lt;/span&gt;
&lt;span class="c"&gt;// I got:      10100-10-1110&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output looked like a date the way binary looks like a number — technically valid, completely unreadable.&lt;/p&gt;

&lt;p&gt;Chaos. The numbers were all shuffled wrong.&lt;/p&gt;

&lt;p&gt;Here's why: Go didn't see a random date. It looked at &lt;code&gt;2020&lt;/code&gt; and tried to find pieces of the reference date (&lt;code&gt;Mon Jan 2 15:04:05 MST 2006&lt;/code&gt;) inside it. It found &lt;code&gt;20&lt;/code&gt; — that's the timezone offset token. It found &lt;code&gt;02&lt;/code&gt; — that's the day. &lt;code&gt;12&lt;/code&gt; — that's the 12-hour clock hour. None of it meant what I wanted.&lt;/p&gt;

&lt;p&gt;The format string isn't a template where &lt;em&gt;any&lt;/em&gt; date works. It has to be &lt;strong&gt;that specific date&lt;/strong&gt; — January 2nd, 2006. That's the one Go knows. Any other date is just a string full of ambiguous numbers it'll try to interpret as tokens, with confusing results.&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;// This is the only date Go understands as a format&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;Println&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;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c"&gt;// ✓&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tattoo it somewhere. &lt;code&gt;2006-01-02&lt;/code&gt;. Year, month, day — from the one reference date. Not your birthday. Not today's date. Not a date that "looks right." The reference date.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Wait, Why?!" Moment
&lt;/h2&gt;

&lt;p&gt;Okay but &lt;em&gt;why&lt;/em&gt; that specific date? Why not just use &lt;code&gt;YYYY&lt;/code&gt; like a normal language?&lt;/p&gt;

&lt;p&gt;This is the part that actually made me laugh once I understood it.&lt;/p&gt;

&lt;p&gt;That reference date — &lt;code&gt;01/02 03:04:05PM '06 -0700&lt;/code&gt; — is special because each component is a &lt;strong&gt;unique number&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Month: &lt;code&gt;01&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Day: &lt;code&gt;02&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Hour: &lt;code&gt;03&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Minute: &lt;code&gt;04&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Second: &lt;code&gt;05&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Year: &lt;code&gt;06&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Timezone offset: &lt;code&gt;07&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They count up: 1, 2, 3, 4, 5, 6, 7. Go uses this sequence so it can unambiguously look at any format string and know &lt;em&gt;exactly&lt;/em&gt; what each piece represents — no token dictionary needed. If it sees &lt;code&gt;06&lt;/code&gt; in your format string, it knows you want the two-digit year. If it sees &lt;code&gt;2006&lt;/code&gt;, it knows you want the four-digit year. If it sees &lt;code&gt;15&lt;/code&gt;, it knows you want 24-hour time (because the reference hour in 24h format is 15:04).&lt;/p&gt;

&lt;p&gt;It's genuinely clever once it clicks. But until it clicks, it feels completely unhinged.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Aha Moment, In Practice
&lt;/h2&gt;

&lt;p&gt;Once I got it, formatting timestamps became almost fun. Here's what correct usage looks like:&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;now&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;// Date only&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// → 2025-01-15&lt;/span&gt;

    &lt;span class="c"&gt;// Date and time&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 15:04:05"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// → 2025-01-15 14:32:05&lt;/span&gt;

    &lt;span class="c"&gt;// More readable&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mon, 02 Jan 2006"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// → Wed, 15 Jan 2025&lt;/span&gt;

    &lt;span class="c"&gt;// For my Net-Cat project&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[2006-01-02 15:04:05]"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// → [2025-01-15 14:32:05]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reference date is always the same: &lt;strong&gt;Mon Jan 2 15:04:05 MST 2006&lt;/strong&gt;. You just rearrange and decorate it however you want your output to look.&lt;/p&gt;

&lt;p&gt;I'd actually recommend keeping that reference date somewhere visible while you're learning Go — a sticky note, a comment at the top of your file, whatever works. You'll need to glance at it more than once.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Go's time formatting is one of those things that feels bizarre at first and obvious in hindsight. Most languages teach you a set of format codes to memorise (&lt;code&gt;%Y&lt;/code&gt;, &lt;code&gt;%m&lt;/code&gt;, &lt;code&gt;YYYY&lt;/code&gt;, etc.) and trust that you'll look them up when you forget them. Go took a different approach: instead of a codebook, it gave you a single example to reference.&lt;/p&gt;

&lt;p&gt;Once you know the reference date, you don't need to memorise anything. You just ask yourself: &lt;em&gt;"How would I write January 2nd, 2006 in the format I want?"&lt;/em&gt; — and that's your format string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For beginners, here's the mental shift:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't think &lt;em&gt;"what token represents the year?"&lt;/em&gt; — think &lt;em&gt;"what does the year 2006 look like in this format?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's a small shift, but it changes everything.&lt;/p&gt;

&lt;p&gt;I really wish someone had framed it that way for me on day one instead of letting me spend twenty minutes typing &lt;code&gt;"YYYY"&lt;/code&gt; into a terminal like a confused golden retriever.&lt;/p&gt;

&lt;p&gt;Learn from my suffering. Use the reference date. Format your timestamps.&lt;/p&gt;

&lt;p&gt;And if your output still looks weird — check whether you're using &lt;code&gt;log.Println()&lt;/code&gt;. Trust me on that one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next up: the actual Net-Cat project, and all the new ways it found to humble me.&lt;/em&gt; 🐹&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Go Beginner Mistake #1: When `log.Println()` Made Me Question `time.Now().Format()`</title>
      <dc:creator>perez odiyo</dc:creator>
      <pubDate>Fri, 05 Jun 2026 16:52:20 +0000</pubDate>
      <link>https://dev.to/perezodiyo/go-beginner-mistake-1-when-logprintln-made-me-question-timenowformat-3ig0</link>
      <guid>https://dev.to/perezodiyo/go-beginner-mistake-1-when-logprintln-made-me-question-timenowformat-3ig0</guid>
      <description>&lt;p&gt;&lt;em&gt;A small bug that taught me to read my tools before blaming my code.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Plan
&lt;/h2&gt;

&lt;p&gt;I was building a &lt;strong&gt;Net-Cat project&lt;/strong&gt; in Go — a simplified version of the classic &lt;code&gt;nc&lt;/code&gt; (netcat) Unix tool. One of the features I wanted was a clean timestamp displayed whenever a client connected or sent a message. Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[2025-01-15 14:32:05] Alice has joined the chat
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple enough, right? I reached for &lt;code&gt;time.Now().Format()&lt;/code&gt; and felt good about 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="n"&gt;timestamp&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 15:04:05"&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"["&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"] Alice has joined the chat"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I ran it, looked at the output, and... something was &lt;em&gt;off&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Confusing Output
&lt;/h2&gt;

&lt;p&gt;Instead of the clean line I expected, my terminal was showing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;2025/01/15 14:32:05 [2025-01-15 14:32:05] Alice has joined the chat
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Two timestamps.&lt;/strong&gt; Right next to each other.&lt;/p&gt;

&lt;p&gt;My first thought? &lt;em&gt;My format string must be broken.&lt;/em&gt; I started Googling &lt;code&gt;time.Now().Format&lt;/code&gt; syntax. I tried different layouts. I rewrote the format string three times. Nothing changed. The double timestamp was still there, mocking me.&lt;/p&gt;

&lt;p&gt;I even briefly wondered if Go had some weird timezone bug. (It did not.)&lt;/p&gt;




&lt;h2&gt;
  
  
  The Culprit: &lt;code&gt;log.Println()&lt;/code&gt; vs &lt;code&gt;fmt.Println()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Here's what I didn't know at the time:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;log.Println()&lt;/code&gt; and &lt;code&gt;fmt.Println()&lt;/code&gt; are NOT the same thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fmt.Println()&lt;/code&gt; is simple. It prints exactly what you give it, adds a newline, and calls it a day.&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: Hello, world!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;log.Println()&lt;/code&gt; is different. It's part of Go's &lt;code&gt;log&lt;/code&gt; package, which is designed for &lt;strong&gt;application logging&lt;/strong&gt; — the kind where you always want to know &lt;em&gt;when&lt;/em&gt; something happened. So by default, &lt;code&gt;log&lt;/code&gt; automatically prepends every message with the current date and 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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: 2025/01/15 14:32:05 Hello, world!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See that prefix? You didn't ask for it. It's just... there. Always. That's the &lt;code&gt;log&lt;/code&gt; package doing its job.&lt;/p&gt;

&lt;p&gt;So when I wrote:&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;timestamp&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 15:04:05"&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"["&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"] Alice has joined the chat"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;log&lt;/code&gt; package saw my message, slapped its own timestamp at the front, and printed both. My code was working perfectly — I just didn't understand the tool I was using.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does &lt;code&gt;log&lt;/code&gt; Do This?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;log&lt;/code&gt; package in Go is built for one specific purpose: &lt;strong&gt;structured application logging&lt;/strong&gt;. When you're debugging a server that's been running for days, or tracing a crash in production, the absolute first thing you need to know is &lt;em&gt;when&lt;/em&gt; something happened.&lt;/p&gt;

&lt;p&gt;So the designers of the &lt;code&gt;log&lt;/code&gt; package made that the default. Every log entry gets a timestamp. You don't have to ask for it.&lt;/p&gt;

&lt;p&gt;You can actually control this behaviour with &lt;code&gt;log.SetFlags()&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="c"&gt;// Remove the automatic timestamp entirely&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;SetFlags&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"No timestamp here!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: No timestamp here!&lt;/span&gt;

&lt;span class="c"&gt;// Or keep just the time, not the date&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;SetFlags&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;Ltime&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Just the time"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: 14:32:05 Just the time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default flag value is &lt;code&gt;log.LstdFlags&lt;/code&gt;, which equals &lt;code&gt;log.Ldate | log.Ltime&lt;/code&gt; — both date and time. That's the source of my double timestamp.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Finally Figured It Out
&lt;/h2&gt;

&lt;p&gt;After enough head-scratching, I stopped trying to fix my &lt;code&gt;time.Now().Format()&lt;/code&gt; code and started asking a different question: &lt;em&gt;"Where is this first timestamp actually coming from?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I removed my custom timestamp entirely and just logged a plain string:&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice has joined the chat"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: 2025/01/15 14:32:05 Alice has joined the chat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There it was. The timestamp wasn't coming from my code at all. I opened the Go docs for the &lt;code&gt;log&lt;/code&gt; package for the first time, and the very first line told me everything:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Package log implements a simple logging package. Each logging operation makes a single call to the Writer's Write method. A Logger can be used simultaneously from multiple goroutines; it guarantees serialized access to the Writer. The default logger writes to standard error and prints the date and time of each logged message."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Date and time of each logged message.&lt;/strong&gt; Right there in the first paragraph. I just hadn't read it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;

&lt;p&gt;For my Net-Cat project, I had two clean options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1:&lt;/strong&gt; Switch to &lt;code&gt;fmt.Println()&lt;/code&gt; and keep full control of formatting.&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;timestamp&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 15:04:05"&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"["&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"] Alice has joined the chat"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: [2025-01-15 14:32:05] Alice has joined the chat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option 2:&lt;/strong&gt; Keep &lt;code&gt;log.Println()&lt;/code&gt; but disable its automatic prefix.&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;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetFlags&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="c"&gt;// Call this once at the start of your program&lt;/span&gt;
&lt;span class="n"&gt;timestamp&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 15:04:05"&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"["&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"] Alice has joined the chat"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: [2025-01-15 14:32:05] Alice has joined the chat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I went with Option 1. &lt;code&gt;fmt&lt;/code&gt; was the right tool for user-facing chat messages; &lt;code&gt;log&lt;/code&gt; is better suited for actual application diagnostics.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Lesson
&lt;/h2&gt;

&lt;p&gt;The bug was never in my &lt;code&gt;time.Now().Format()&lt;/code&gt; code. It was in my assumption that &lt;code&gt;log.Println()&lt;/code&gt; behaved like &lt;code&gt;fmt.Println()&lt;/code&gt;. They share a similar name and do similar things on the surface, but they're built for completely different jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The takeaway for new Go developers:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When something isn't working, before you rewrite your logic — make sure you understand every tool you're using.&lt;/strong&gt; A quick trip to the official Go docs (&lt;a href="https://pkg.go.dev" rel="noopener noreferrer"&gt;pkg.go.dev&lt;/a&gt;) can save you an hour of chasing the wrong bug.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use &lt;code&gt;fmt&lt;/code&gt; when you're talking &lt;strong&gt;to the user&lt;/strong&gt;.&lt;br&gt;
Use &lt;code&gt;log&lt;/code&gt; when you're talking &lt;strong&gt;to yourself&lt;/strong&gt; (or your future debugging self).&lt;/p&gt;

&lt;p&gt;And when output looks weird? Don't assume your code is wrong. Ask where &lt;em&gt;every part&lt;/em&gt; of that output is coming from.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Happy coding — and may your timestamps never double up again.&lt;/em&gt; 🕐&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>debugging</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
