{
    "version": "https://jsonfeed.org/version/1",
    "title": "Ozan Sazak - sazak.io",
    "home_page_url": "https://sazak.io/articles",
    "description": "Stay tuned for the latest articles, talks and reading groups by me.",
    "author": {
        "name": "Ozan Sazak",
        "url": "https://sazak.io"
    },
    "items": [
        {
            "id": "https://sazak.io/articles/visual-guide-to-go-maps-hash-tables-2025-10-26",
            "content_html": "<p>In the <a href=\"/articles/visual-guide-to-slices-in-go-2024-03-25\" target=\"_blank\">previous article</a>, we explored how slices work under the hood. Today, we&#39;ll dive into another fundamental Go data structure: <strong>maps</strong>. We&#39;ll see how Go implements maps as hash tables, how they handle collisions, and how they grow dynamically.</p>\n<blockquote data-quote-character=\"sazak-explain\" class=\"quote-character\"><p> This will be a two part series. This first part will cover the old <code>map</code> implementation which was in use until Go 1.24. The second part will cover the new <code>map</code> implementation using swiss tables. <!--Although the current implementation is different than the legacy one, it's still worth learning. At the end of this article, you'll find [exercises](#exercises) to test your understanding.--></p>\n</blockquote>\n<p>The mini note below covers the basics of hash tables and how they are implemented in simple terms. Feel free to skip it if you already know the basics.</p>\n<p><collapsible-item title=\"What is a hash table?\" kind=\"mini-note\" readingtime=\"3\" parsetextfrom=\"mini-notes/primer-on-hash-tables.md\" parsedcontent=\"&lt;p&gt;Hash tables are one of the most fundamental data structures in Computer Science.&lt;/p&gt;\n&lt;h2 id=&#34;what-problem-do-hash-tables-solve&#34;&gt;What problem do hash tables solve?&lt;/h2&gt;\n&lt;p&gt;Let&#39;s say you&#39;re building a phone book application. You want to look up someone&#39;s phone number by their name. Without a hash table, you might store the data in an array and search through it linearly:&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;// O(n) lookup time\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;entry&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;phoneBook&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;entry&lt;/span&gt;&lt;span style=&#34;&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;&#34;&gt;Name&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;==&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;entry&lt;/span&gt;&lt;span style=&#34;&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;&#34;&gt;Number&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This works, but it&#39;s slow. If you have a million entries, you might need to check all million in the worst case.&lt;/p&gt;\n&lt;p&gt;Hash tables solve this by converting keys (like names) into array indices using a &lt;strong&gt;hash function&lt;/strong&gt;, allowing nearly instant lookups.&lt;/p&gt;\n&lt;h2 id=&#34;how-hashing-works&#34;&gt;How hashing works&lt;/h2&gt;\n&lt;p&gt;At its core, a hash table is an array of &lt;strong&gt;buckets&lt;/strong&gt;. Each bucket can hold one or more key-value pairs. When you insert or look up a key, the hash function converts it to an integer:&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;hash&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;14523&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;hash&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Ozan&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;9217&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;hash&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Gokce&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;100225&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The hash value is then mapped to a bucket index using modulo operation:&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;bucketIndex&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;hash&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;numberOfBuckets&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;\n&lt;p&gt;The &lt;code&gt;hash&lt;/code&gt; function here may accept different kinds of types as parameter, such as strings (as shown here), numbers, or even more complex objects. Some programming languages gives the user the ability to implement custom object specific hash functions which would then be used in the &lt;code&gt;hash&lt;/code&gt; function.&lt;/p&gt;\n&lt;/blockquote&gt;\n&lt;p&gt;Hash functions can implement different logics inside. Here is a fairly simple one, calculating the hash of a &lt;code&gt;string&lt;/code&gt; (as an array of &lt;code&gt;byte&lt;/code&gt;s) by summing up the ASCII-equivalent values of each character in it:&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;hash&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;key&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;[]&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;byte&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;buckets&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;&#34;&gt;h&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;key&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;&#34;&gt;h&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;key&lt;/span&gt;&lt;span style=&#34;&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;&#34;&gt;])&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;h&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;buckets&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, the key &amp;quot;Alice&amp;quot; will map to the 222nd bucket:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;&#39;A&#39; = 65, &#39;l&#39; = 108, &#39;i&#39; = 105, &#39;c&#39; = 99, and &#39;e&#39; = 101 in ASCII table&lt;/li&gt;\n&lt;li&gt;Sum mod 256 (if we had 256 buckets) = 222&lt;/li&gt;\n&lt;li&gt;So, the bucket index is 222&lt;/li&gt;\n&lt;/ul&gt;\n&lt;p&gt;&lt;img src=&#34;/assets/articles/visual-guide-go-map/hash-table-2.png&#34; alt=&#34;&#34; loading=&#34;lazy&#34;&gt;&lt;/p&gt;\n&lt;blockquote&gt;\n&lt;p&gt;Real-world hash functions are much more sophisticated. They need to distribute keys evenly, be fast to compute, and minimize collisions (different keys producing the same hash). Production hash algorithms include MurmurHash, xxHash, etc.&lt;/p&gt;\n&lt;/blockquote&gt;\n&lt;h2 id=&#34;inserting-data&#34;&gt;Inserting data&lt;/h2&gt;\n&lt;p&gt;Let&#39;s say we have a hash table for storing people to their companies. The table already contains Alice, Bob, and Eve&#39;s workplace information.&lt;/p&gt;\n&lt;p&gt;Let&#39;s walk through inserting &amp;quot;John&amp;quot; -&amp;gt; &amp;quot;Amazon&amp;quot; into the table.&lt;/p&gt;\n&lt;ol&gt;\n&lt;li&gt;Apply the hash function to &amp;quot;John&amp;quot; to get the bucket index. Let&#39;s say it&#39;s bucket 2.&lt;/li&gt;\n&lt;li&gt;Go to bucket 2 in our bucket array.&lt;/li&gt;\n&lt;li&gt;Place the key-value pair (&amp;quot;John&amp;quot;, &amp;quot;Amazon&amp;quot;) in bucket 2. If the bucket already has entries (a &lt;strong&gt;collision&lt;/strong&gt;), add it to the bucket&#39;s list.&lt;/li&gt;\n&lt;/ol&gt;\n&lt;p&gt;&lt;img src=&#34;/assets/articles/visual-guide-go-map/hash-table-1.png&#34; alt=&#34;&#34; loading=&#34;lazy&#34;&gt;&lt;/p&gt;\n&lt;p&gt;With this structure, searching for John&#39;s workplace is pretty fast: hash &amp;quot;John&amp;quot;, go to bucket 2, and retrieve the value.&lt;/p&gt;\n&lt;h3 id=&#34;what-happens-when-multiple-keys-hash-to-the-same-bucket&#34;&gt;What happens when multiple keys hash to the same bucket?&lt;/h3&gt;\n&lt;p&gt;This is called &lt;strong&gt;collision&lt;/strong&gt;. There are different strategies to handle collisions, such as open addressing (find the next available bucket), or Go&#39;s approach of using overflow buckets (in Go versions before 1.24). The implementation details vary, but the concept remains: distribute keys across buckets and handle collisions gracefully.&lt;/p&gt;\n&lt;h2 id=&#34;performance&#34;&gt;Performance&lt;/h2&gt;\n&lt;p&gt;Hash tables give us &lt;strong&gt;O(1) average case&lt;/strong&gt; time complexity for insertions, lookups, and deletions. Compare this to other data structures:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;&lt;strong&gt;Array (unsorted)&lt;/strong&gt;: O(n) for search&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Binary search tree&lt;/strong&gt;: O(log n) for search&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Hash table&lt;/strong&gt;: O(1) average for search&lt;/li&gt;\n&lt;/ul&gt;\n&lt;table&gt;\n&lt;thead&gt;\n&lt;tr&gt;\n&lt;th&gt;Operation&lt;/th&gt;\n&lt;th&gt;Average&lt;/th&gt;\n&lt;th&gt;Worst Case&lt;/th&gt;\n&lt;/tr&gt;\n&lt;/thead&gt;\n&lt;tbody&gt;\n&lt;tr&gt;\n&lt;td&gt;Insert(k, v)&lt;/td&gt;\n&lt;td&gt;O(1)&lt;/td&gt;\n&lt;td&gt;O(n)&lt;/td&gt;\n&lt;/tr&gt;\n&lt;tr&gt;\n&lt;td&gt;Search(k)&lt;/td&gt;\n&lt;td&gt;O(1)&lt;/td&gt;\n&lt;td&gt;O(n)&lt;/td&gt;\n&lt;/tr&gt;\n&lt;tr&gt;\n&lt;td&gt;Delete(k)&lt;/td&gt;\n&lt;td&gt;O(1)&lt;/td&gt;\n&lt;td&gt;O(n)&lt;/td&gt;\n&lt;/tr&gt;\n&lt;/tbody&gt;\n&lt;/table&gt;\n&lt;p&gt;Using hash tables lower the time complexity of key lookup to &lt;code&gt;O(1)&lt;/code&gt; theoretically.&lt;/p&gt;\n\" readingtime=\"180\"></collapsible-item></p>\n<p>Coming back to the main topic, let&#39;s see how maps are implemented in Go.</p>\n<p>In Go, before version 1.24, <strong>a map is a hash table implementation</strong> that stores key-value pairs. Unlike slices which use integer indices, maps allow you to use any comparable<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> type as a key to access values efficiently. A type is comparable if values of that type can be compared with <code>==</code> and <code>!=</code> operators.</p>\n<p>Here&#39;s how a map is defined in the <a href=\"https://github.com/golang/go/blob/dd8b7ad9268c2fbde675132a41b4e4da02eef94d/src/runtime/map.go#L109\" target=\"_blank\">Go runtime</a>:</p>\n<pre data-filename=\"go/src/runtime/map.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">hmap</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">count</span><span style=\"\">      </span><span style=\"color:#8be9fd\">int</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"\">flags</span><span style=\"\">      </span><span style=\"color:#8be9fd\">uint8</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">    </span><span style=\"\">B</span><span style=\"\">          </span><span style=\"color:#8be9fd\">uint8</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">    </span><span style=\"\">noverflow</span><span style=\"\">  </span><span style=\"color:#8be9fd\">uint16</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">    </span><span style=\"\">hash0</span><span style=\"\">      </span><span style=\"color:#8be9fd\">uint32</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">    </span><span style=\"\">buckets</span><span style=\"\">    </span><span style=\"\">unsafe</span><span style=\"\">.</span><span style=\"\">Pointer</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">    </span><span style=\"\">oldbuckets</span><span style=\"\"> </span><span style=\"\">unsafe</span><span style=\"\">.</span><span style=\"\">Pointer</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">    </span><span style=\"\">nevacuate</span><span style=\"\">  </span><span style=\"color:#8be9fd\">uintptr</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">    </span><span style=\"\">extra</span><span style=\"\">      </span><span style=\"color:#ff79c6\">*</span><span style=\"\">mapextra</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>When you create a map like <code>m := make(map[string]int)</code>, Go allocates this <code>hmap</code> structure under the hood. The map you&#39;re working with is actually a pointer to this structure, which is why maps behave like reference types in Go<sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup>.</p>\n<p>The important fields in this data structure are:</p>\n<ul>\n<li><code>count</code>: Number of key-value pairs currently stored in the map</li>\n<li><code>B</code>: Number of bucket bits (not the bucket count itself). The actual number of buckets is <code>2^B</code> (or <code>1 &lt;&lt; B</code> in Go). So if <code>B</code> is 3, you have 8 buckets.</li>\n<li><code>buckets</code>: Pointer to an array of buckets where key-value pairs are stored</li>\n<li><code>hash0</code>: A random seed used by the hash function. This seed is generated when the map is created and it makes the hash function non-deterministic.</li>\n</ul>\n<blockquote data-quote-character=\"sazak-explain\" class=\"quote-character\"><p> The <code>oldbuckets</code> and <code>nevacuate</code> fields are used during map growth, which we&#39;ll explore in detail later.</p>\n</blockquote>\n<p>Let&#39;s start with a simple map creation:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">userAges</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;alice&#34;</span><span style=\"\">:</span><span style=\"\"> </span><span style=\"color:#bd93f9\">25</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;bob&#34;</span><span style=\"\">:</span><span style=\"\">   </span><span style=\"color:#bd93f9\">30</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;carol&#34;</span><span style=\"\">:</span><span style=\"\"> </span><span style=\"color:#bd93f9\">28</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>This creates a map with string keys and integer values. But how does Go organize this data internally?</p>\n<h2 id=\"buckets\">Buckets</h2>\n<p>When you work with a map, the Go runtime doesn&#39;t just store your key-value pairs in a simple array. Instead, it uses a <strong>hash table with buckets</strong>. Think of buckets as containers that hold multiple key-value pairs, and the hash table is an array of these buckets.</p>\n<p>The key idea is, when you insert a key-value pair, Go hashes the key to determine which bucket it belongs to. All keys that hash to the same bucket are stored together. This organization allows for fast lookups. Go can hash your key once and immediately know which bucket to search in, rather than scanning through all the data.</p>\n<p>And here&#39;s how our <code>userAges</code> map looks like internally, at a high level:</p>\n<p><mapview name=\"userAges map[string]int\" buckets=\"8\" items=\"alice:25,bob:30,carol:28\" theme=\"blue\"></mapview></p>\n<p>You can see the map has <strong>8 buckets</strong> (numbered 0-7), which means <code>B = 3</code> since 2^3 = 8.</p>\n<p>Each colored cell represents a bucket that contains at least one key-value pair. The three keys we inserted, <code>&#34;alice&#34;</code>, <code>&#34;bob&#34;</code>, and <code>&#34;carol&#34;</code> were hashed and distributed across different buckets in the array. Notice they didn&#39;t all go to the same bucket; the hash function distributed them to help balance the load.</p>\n<p>The gray buckets are empty, ready to receive new entries as we add more key-value pairs to the map.</p>\n<p>Go maps use <strong>overflow pointers</strong> to handle collisions. When a bucket becomes full, instead of reorganizing everything, Go simply allocates a new overflow bucket and links it to the full one, creating a short chain.</p>\n<h3 id=\"bucket-structure\">Bucket Structure</h3>\n<p>Now let&#39;s look at what&#39;s inside each bucket. Each bucket in Go can hold up to <strong>8 key-value pairs</strong>. You can see that this value is hardcoded in <a href=\"https://github.com/golang/go/blob/dd8b7ad9268c2fbde675132a41b4e4da02eef94d/src/internal/abi/map.go\" target=\"_blank\">Go source code</a>:</p>\n<pre data-filename=\"go/src/internal/abi/map.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#ff79c6\">package</span><span style=\"\"> </span><span style=\"\">abi</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">const</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Maximum number of key/elem pairs a bucket can hold.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"\">MapBucketCountBits</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">3</span><span style=\"\"> </span><span style=\"color:#6272a4\">// log2 of number of elements in a bucket.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"\">MapBucketCount</span><span style=\"\">     </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"\"> </span><span style=\"\">MapBucketCountBits</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7</span><span style=\"\"><span style=\"\"></span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p>Here&#39;s the actual bucket structure:</p>\n<pre data-filename=\"go/src/runtime/map.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">bmap</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">tophash</span><span style=\"\"> </span><span style=\"\">[</span><span style=\"\">abi</span><span style=\"\">.</span><span style=\"\">MapBucketCount</span><span style=\"\">]</span><span style=\"color:#8be9fd\">uint8</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>The <code>tophash</code> array is an interesting optimization. It stores the top 8 bits of each key&#39;s hash value. When Go searches for a key in a bucket, it first scans the <code>tophash</code> array. Only when it finds a matching tophash, the key comparison is done. This mean that Go can quickly skip over slots that definitely don&#39;t contain the key, without having to compare complex key types.</p>\n<blockquote data-quote-character=\"husky-1-1\" class=\"quote-character\"><p> The actual keys and values are stored after the <code>tophash</code> array, but they&#39;re not visible in the struct definition because their types are determined at runtime. Go knows the types of your keys and values at compile time, so it can calculate the correct memory layout dynamically.</p>\n</blockquote>\n<p>If you search through the runtime code in Go source code (as I did), you can find the actual creation process of a bucket:</p>\n<pre data-filename=\"go/src/cmd/compile/internal/reflectdata/reflect.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">MapBucketType</span><span style=\"\">(</span><span style=\"\">t</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">types</span><span style=\"\">.</span><span style=\"\">Type</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">types</span><span style=\"\">.</span><span style=\"\">Type</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Builds a type representing a Bucket structure for\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">// the given map type. This type is not visible to users -\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">// we include only enough information to generate a correct GC\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">// program for it.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">// Make sure this stays in sync with runtime/map.go.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">//\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">//\tA &#34;bucket&#34; is a &#34;struct&#34; {\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">//\t      tophash [abi.MapBucketCount]uint8\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">//\t      keys [abi.MapBucketCount]keyType\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">//\t      elems [abi.MapBucketCount]elemType\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">//\t      overflow *bucket\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">//\t    }\n</span></span></span></code></pre><p>Let&#39;s see how our example map looks with bucket details:</p>\n<p><mapbucket bucket=\"0\" tophash=\"ab,cd,ef,00,00,00,00,00\" keys=\"alice,bob,carol,,,,,,\" values=\"25,30,28,,,,,,\" theme=\"blue\"></mapbucket></p>\n<p>Here, you&#39;re looking at bucket 0 of our <code>userAges</code> map. Let&#39;s break down what each part means:</p>\n<p><strong>The tophash array:</strong> <code>[ab, cd, ef, 00, 00, 00, 00, 00]</code></p>\n<p>The first three slots contain tophash values (<code>0xAB</code>, <code>0xCD</code>, <code>0xEF</code>). These are the top 8 bits from hashing &#34;alice&#34;, &#34;bob&#34;, and &#34;carol&#34; respectively. The remaining five slots show <code>0x00</code>, indicating they&#39;re empty and available for new entries.</p>\n<p><strong>The keys array:</strong> <code>[alice, bob, carol, _, _, _, _, _]</code></p>\n<p>The first three positions hold our actual keys. The empty positions (shown with commas or underscores) are unused slots waiting for new key-value pairs.</p>\n<p><strong>The values array:</strong> <code>[25, 30, 28, _, _, _, _, _]</code></p>\n<p>The values are stored in the same order as their corresponding keys. Alice&#39;s age (25) is at index 0, Bob&#39;s (30) at index 1, and Carol&#39;s (28) at index 2.</p>\n<h2 id=\"hash-function-and-key-distribution\">Hash Function and Key Distribution</h2>\n<p>When you insert a key-value pair into a map, Go needs to decide which bucket to place it in. This is where the hash function comes in to play.</p>\n<p>Let&#39;s say we&#39;re inserting <code>&#34;gokce&#34;: 25</code> into our map. Here&#39;s what Go does step by step.</p>\n<p>First, Go applies a hash function<sup id=\"fnref:3\"><a href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\">3</a></sup> to the key along with the map&#39;s random seed (<code>hash0</code>):</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">hash</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">hashFunction</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;gokce&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">.</span><span style=\"\">hash0</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\"></span><span style=\"color:#6272a4\">// Let&#39;s say this produces: 0xAB7F3C2E4D1A6B8F (64-bit hash)\n</span></span></span></code></pre><p>Go then uses the <strong>lower B bits</strong> of the hash to select which bucket to use. If our map has <code>B = 3</code> (meaning 8 buckets), Go takes the lowest 3 bits:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">bucketIndex</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">hash</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"color:#bd93f9\">1</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"\"> </span><span style=\"\">B</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">-</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\">  </span><span style=\"color:#6272a4\">// Bitwise AND with mask\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"color:#6272a4\">// If hash ends in ...110 (binary), bucketIndex = 6\n</span></span></span></code></pre><p>This logic is defined in the <code>bucketMask</code> function in Go source code:</p>\n<pre data-filename=\"go/src/runtime/map.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">// bucketShift returns 1&lt;&lt;b, optimized for code generation.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">bucketShift</span><span style=\"\">(</span><span style=\"\">b</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uint8</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uintptr</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Masking the shift amount allows overflow checks to be elided.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">uintptr</span><span style=\"\">(</span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">b</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">goarch</span><span style=\"\">.</span><span style=\"\">PtrSize</span><span style=\"color:#ff79c6\">*</span><span style=\"color:#bd93f9\">8</span><span style=\"\"> </span><span style=\"color:#ff79c6\">-</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\"></span><span style=\"color:#6272a4\">// bucketMask returns 1&lt;&lt;b - 1, optimized for code generation.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">bucketMask</span><span style=\"\">(</span><span style=\"\">b</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uint8</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uintptr</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#50fa7b\">bucketShift</span><span style=\"\">(</span><span style=\"\">b</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">-</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>This is much faster than using the modulo operator (<code>%</code>). Since the bucket count is always a power of 2, we can use a bitwise AND instead.</p>\n<p>After that, Go takes the <strong>top 8 bits</strong> of the hash and stores them in the bucket&#39;s <code>tophash</code> array and finds an empty slot in the selected bucket and stores the tophash, key, and value there.</p>\n<p>Let&#39;s see how different keys get distributed across buckets:</p>\n<p><mapview name=\"Distribution Example\" buckets=\"8\" items=\"alice:25,bob:30,carol:28,dave:35,eve:22\" theme=\"green\" showhashdist=\"1\"></mapview></p>\n<h2 id=\"handling-collisions\">Handling Collisions</h2>\n<p>So what happens when multiple keys hash to the same bucket? This is called a <strong>collision</strong>, and it&#39;s inevitable in hash tables. The hash function tries to distribute keys evenly, but with a limited number of buckets some will inevitably end up with more entries than others.</p>\n<p>Let&#39;s say we have bucket 0 with three entries: <code>&#34;alice&#34;</code>, <code>&#34;bob&#34;</code>, and <code>&#34;carol&#34;</code>. Now we keep adding more keys that also hash to bucket 0 (oops!)</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">userAges</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;dave&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">35</span><span style=\"\">    </span><span style=\"color:#6272a4\">// Hashes to bucket 0, slot 3\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">userAges</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;eve&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">22</span><span style=\"\">     </span><span style=\"color:#6272a4\">// Hashes to bucket 0, slot 4\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">userAges</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;frank&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\">   </span><span style=\"color:#6272a4\">// Hashes to bucket 0, slot 5\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">userAges</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;grace&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">29</span><span style=\"\">   </span><span style=\"color:#6272a4\">// Hashes to bucket 0, slot 6\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">userAges</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;henry&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">31</span><span style=\"\">   </span><span style=\"color:#6272a4\">// Hashes to bucket 0, slot 7\n</span></span></span></code></pre><p>At this point, bucket 0 has all 8 slots filled. What happens when we try to add one more key that hashes to the same bucket?</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">userAges</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;ivan&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">26</span><span style=\"\">    </span><span style=\"color:#6272a4\">// Also hashes to bucket 0... but it&#39;s full!\n</span></span></span></code></pre><p>Go doesn&#39;t reorganize the entire map at this point. Instead, it allocates an <strong>overflow bucket</strong> and links it to the original bucket. The overflow bucket is just another <code>bmap</code> structure -with the actual key and value arrays defined dynamically in runtime- and the original bucket&#39;s <code>overflow</code> pointer now points to it.</p>\n<p>Here&#39;s how overflow buckets work:</p>\n<p><mapbucket bucket=\"0\" tophash=\"ab,cd,ef,12,34,56,78,9a\" keys=\"alice,bob,carol,dave,eve,frank,grace,henry\" values=\"25,30,28,35,22,32,29,31\" overflow=\"true\" theme=\"yellow\"></mapbucket></p>\n<p>The overflow bucket is linked to the main bucket, creating a short chain. When Go looks up a key in bucket <code>0</code>, it first checks the main bucket, and if the key isn&#39;t found there, it follows the overflow pointer to check the overflow bucket.</p>\n<p>This chaining approach is simple and efficient for small numbers of overflows. However, if you have many overflow buckets, lookups become slower (you have to scan multiple buckets). That&#39;s why Go monitors overflow bucket usage and triggers map growth when there are too many of them.</p>\n<p><newslettercard></newslettercard></p>\n<h2 id=\"looking-up-values\">Looking Up Values</h2>\n<p>When you access a value with <code>value := userAges[&#34;alice&#34;]</code>, it might look like a simple operation, but there&#39;s quite a bit happening under the hood. Let&#39;s take a look at what happens when a map value is accessed by a key.</p>\n<p><mapbucket bucket=\"0\" tophash=\"ab,cd,ef,00,00,00,00,00\" keys=\"alice,bob,carol,,,,,,\" values=\"25,30,28,,,,,,\" highlight=\"alice\" theme=\"blue\"></mapbucket></p>\n<ol>\n<li>Go computes the hash of <code>&#34;alice&#34;</code> using the map&#39;s hash function and seed:</li>\n</ol>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">hash</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">hashFunction</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;alice&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">hash0</span><span style=\"\">)</span><span style=\"\">  </span><span style=\"color:#6272a4\">// e.g., 0xAB7F3C2E4D1A6B8F\n</span></span></span></code></pre><ol start=\"2\">\n<li>Using the lower <code>B</code> bits of the hash, Go calculates which bucket to search the key inside:</li>\n</ol>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">bucketIndex</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">hash</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"color:#bd93f9\">1</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"\"> </span><span style=\"\">B</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">-</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\">  </span><span style=\"color:#6272a4\">// e.g., bucket 6\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">tophash</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">hash</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&gt;&gt;</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#bd93f9\">64</span><span style=\"\"> </span><span style=\"color:#ff79c6\">-</span><span style=\"\"> </span><span style=\"color:#bd93f9\">8</span><span style=\"\">)</span><span style=\"\">           </span><span style=\"color:#6272a4\">// e.g., 0xAB\n</span></span></span></code></pre><ol start=\"3\">\n<li>Now Go walks through the bucket&#39;s <code>tophash</code> array looking for a match. Let&#39;s say bucket 6 looks like this:</li>\n</ol>\n<pre><code>tophash: [0xAB, 0xCD, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00]\nkeys:    [&#34;alice&#34;, &#34;bob&#34;, &#34;carol&#34;, ...]\n</code></pre>\n<p>Go scans the tophash array, sees that the value at index 0 matches the tophash value of the key, and now it knows exactly where to look at. After retrieving the value at the same index in the values section of the bucket and returns it.</p>\n<p>If Go scans all tophash entries (including any overflow buckets) without finding a match, it returns the <strong>zero value</strong> of the map&#39;s value type.</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">value</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">userAges</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;alice&#34;</span><span style=\"\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">    </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;Alice is %d years old\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">value</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\"> </span><span style=\"color:#ff79c6\">else</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#6272a4\">// value is 0 (zero value for int)\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">    </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;Alice not found, got zero value: %d\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">value</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">8</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>When accessing a non-existent key, Go returns the <strong>zero value</strong> of the map&#39;s value type (<code>0</code> for numbers, <code>&#34;&#34;</code> for strings, <code>nil</code> for pointers, etc.). The two-value form (<code>value, ok</code>) lets you distinguish between a key that exists with a zero value and a key that doesn&#39;t exist at all.</p>\n<blockquote data-quote-character=\"sazak-explain\" class=\"quote-character\"><p> A return of <code>(&#34;&#34;, true)</code> and <code>(&#34;&#34;, false)</code> are not the same. The first one means that there was actually an entry in the map with the specified key, which value is an empty string. The second one means that there were no value associated with that key.</p>\n</blockquote>\n<p>This is why checking <code>if m[&#34;key&#34;] != 0</code> can be ambiguous, the key might not exist, or it might exist with a zero value. Always use the two-value form when you need to distinguish these cases.</p>\n<h2 id=\"map-growth\">Map Growth</h2>\n<p>As you add more key-value pairs to a map, performance would degrade if Go kept using the same number of buckets. With more entries squeezed into the same buckets, lookups would require scanning longer bucket chains, making operations slower.</p>\n<p>That&#39;s why maps grow dynamically. Go monitors the map&#39;s health and triggers growth when performance would suffer.</p>\n<blockquote data-quote-character=\"husky-1\" class=\"quote-character\"><p> Go runtime decides on whether to grow the map or not is based on <strong>load factor</strong>, which is the average number of key-value pairs per bucket.</p>\n</blockquote>\n<p>A map grows when either of these conditions is met:</p>\n<h3 id=\"condition-1-high-load-factor\">Condition 1: High load factor</h3>\n<p>The average number of key-value pairs per bucket exceeds <strong>6.5</strong> (load factor threshold). This is calculated as:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">loadFactor</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">count</span><span style=\"\"> </span><span style=\"color:#ff79c6\">/</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#bd93f9\">1</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"\"> </span><span style=\"\">B</span><span style=\"\">)</span><span style=\"\">  </span><span style=\"color:#6272a4\">// count / numberOfBuckets\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">loadFactor</span><span style=\"\"> </span><span style=\"\">&gt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">6.5</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#6272a4\">// Trigger growth\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>Why 6.5? That number comes from 80% threshold, as it&#39;s defined in Go runtime source code. It&#39;s a balance between memory usage and performance, a sweet spot where you don&#39;t waste too much memory but also don&#39;t have too many overflow buckets yet.</p>\n<p>Let&#39;s see an example. Say we have a map with 4 buckets that has accumulated 28 entries:</p>\n<p><strong>Before Growth (load factor = 7.0):</strong><br/>\n<mapview name=\"High Load Factor Map\" buckets=\"4\" items=\"gokce:25,ozan:26,carol:28,dave:35,alp:26,frank:32,grace:29,henry:31,baris:18,jack:33,akin:26,leo:26,mary:31,nick:29,olivia:23,paul:36,sulo:31,rachel:30,sam:28,tina:32,james:18,victor:27,wendy:31,bob:30,alice:25,zack:33,yigit:25,ben:30\" theme=\"yellow\" loadfactor=\"7\"></mapview></p>\n<p>The load factor is 28 / 4 = 7.0, which exceeds the 6.5 threshold. Many buckets are overflowing, creating long chains that slow down lookups.</p>\n<p>In this case, the runtime performs a <strong>regular growth</strong> by doubling the bucket count. Here&#39;s what happens:</p>\n<ol>\n<li>\n<p>Go increments <code>B</code> by 1<sup id=\"fnref:4\"><a href=\"#fn:4\" class=\"footnote-ref\" role=\"doc-noteref\">4</a></sup>, which doubles the bucket count. If you had 4 buckets (<code>B == 2</code>), you now have 8 buckets (<code>B == 3</code>). The new bucket array is allocated, but the old buckets remain in place.</p>\n</li>\n<li>\n<p>The <code>hmap.buckets</code> pointer is updated to point to the new bucket array, and <code>hmap.oldbuckets</code> is set to point to the old buckets. The map is now in a <strong>growing</strong> state.</p>\n</li>\n<li>\n<p>Runtime starts an <strong>incremental evacuation</strong> process, where it doesn&#39;t move all key-value pairs immediately. Instead, it evacuates entries gradually during normal map operations. We&#39;ll discuss this in detail in the next section.</p>\n</li>\n</ol>\n<p><strong>After Growth (load factor = 3.5):</strong><br/>\n<mapview name=\"After Regular Growth\" buckets=\"8\" items=\"gokce:25,ozan:26,carol:28,dave:35,alp:26,frank:32,grace:29,henry:31,baris:18,jack:33,akin:26,leo:26,mary:31,nick:29,olivia:23,paul:36,sulo:31,rachel:30,sam:28,tina:32,james:18,victor:27,wendy:31,bob:30,alice:25,zack:33,yigit:25,ben:30\" theme=\"green\" loadfactor=\"3.5\"></mapview></p>\n<p>Now with 8 buckets, the load factor drops to 28 / 8 = 3.5, which is well below the threshold. The entries are redistributed more evenly, and overflow chains are reduced or eliminated.</p>\n<h3 id=\"condition-2-too-many-overflow-buckets\">Condition 2: Too many overflow buckets</h3>\n<p>Even with a low load factor, if there are too many overflow buckets relative to the base bucket count, Go triggers a different type of growth. This happens when keys cluster unevenly, some buckets overflow while others stay mostly empty.</p>\n<p>In this case, Go performs a <strong>same-size growth</strong> which reorganizes the data without adding more buckets. Runtime allocates a new bucket array with the same size as the current one (<code>B</code> stays the same). As entries are evacuated from old buckets to new ones, overflow chains are broken up. Keys that previously shared a bucket with many others might now be distributed more evenly, reducing overflow buckets. This process eliminates overflow buckets that accumulated over time due to deletions or poor initial distribution, making the map more cache-friendly.</p>\n<blockquote data-quote-character=\"beaver-question\" class=\"quote-character\"><p> Why would a map grow without increasing bucket count?</p>\n</blockquote>\n<p>When keys cluster in specific buckets due to hash patterns, you might have many overflow buckets even with a low overall load factor. For example, you might have a map with 100 entries across 16 buckets (load factor = 6.25, below the threshold), but if 80 entries landed in just 2 buckets, you&#39;d have many overflow buckets. Same size growth reorganizes the data to improve performance without allocating more buckets.</p>\n<p>Here&#39;s how this logic is implemented in <a href=\"https://github.com/golang/go/blob/dd8b7ad9268c2fbde675132a41b4e4da02eef94d/src/runtime/map.go#L220\" target=\"_blank\">Go source code</a>:</p>\n<pre data-filename=\"go/src/runtime/map.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">// incrnoverflow increments h.noverflow.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\">// noverflow counts the number of overflow buckets.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"color:#6272a4\">// This is used to trigger same-size map growth.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"color:#6272a4\">// See also tooManyOverflowBuckets.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"color:#6272a4\">// To keep hmap small, noverflow is a uint16.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"color:#6272a4\">// When there are few buckets, noverflow is an exact count.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"color:#6272a4\">// When there are many buckets, noverflow is an approximate count.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">h</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">hmap</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#50fa7b\">incrnoverflow</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">...</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><h3 id=\"incremental-evacuation\">Incremental Evacuation</h3>\n<p>Here&#39;s one of the cool aspects of Go&#39;s map implementation: <strong>incremental evacuation</strong>. Instead of moving all entries at once when the map grows (which could freeze your program for milliseconds on a large map), Go runtime spreads the work across many operations.</p>\n<p>Here&#39;s how it works:</p>\n<ol>\n<li>During growth, both old and new buckets exist and their references are held in <code>hmap</code> in the <code>oldbuckets</code> and <code>buckets</code> fields. When you perform any operation on the map, Go checks if the map is growing:</li>\n</ol>\n<pre data-filename=\"go/src/runtime/map.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">h</span><span style=\"\">.</span><span style=\"color:#50fa7b\">growing</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#50fa7b\">growWork</span><span style=\"\">(</span><span style=\"\">t</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">h</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">bucket</span><span style=\"\">)</span><span style=\"\">  </span><span style=\"color:#6272a4\">// Evacuate some pairs\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><ol start=\"2\">\n<li>\n<p>Whenever a value is inserted to, deleted from, or looked up in the map, Go evacuates at least one bucket (and possibly more) from the old array to the new array. The <code>nevacuate</code> field in the <code>hmap</code> structure tracks which old buckets have been evacuated.</p>\n</li>\n<li>\n<p>During the growth period, when you look up a key, Go might need to check the old buckets if that bucket hasn&#39;t been evacuated yet. The evacuation state markers in the <code>tophash</code> array (we&#39;ll see these shortly) tell Go whether to look in the old or new buckets.</p>\n</li>\n</ol>\n<p>An example code snippet from the Go source code, shows how the runtime handles an edge case of iterating through key/value pairs in the map during a grow:</p>\n<pre data-filename=\"go/src/runtime/map.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">checkBucket</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"\">noCheck</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;&amp;</span><span style=\"\"> </span><span style=\"\">!</span><span style=\"\">h</span><span style=\"\">.</span><span style=\"color:#50fa7b\">sameSizeGrow</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#6272a4\">// Special case: iterator was started during a grow to a larger size\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">        </span><span style=\"color:#6272a4\">// and the grow is not done yet. We&#39;re working on a bucket whose\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">        </span><span style=\"color:#6272a4\">// oldbucket has not been evacuated yet. Or at least, it wasn&#39;t\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">        </span><span style=\"color:#6272a4\">// evacuated when we started the bucket. So we&#39;re iterating\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">        </span><span style=\"color:#6272a4\">// through the oldbucket, skipping any keys that will go\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">        </span><span style=\"color:#6272a4\">// to the other new bucket (each oldbucket expands to two\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">        </span><span style=\"color:#6272a4\">// buckets during a grow).\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">...</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><ol start=\"4\">\n<li>When doubling the bucket count (regular growth), each old bucket&#39;s entries are split between two new buckets:</li>\n</ol>\n<ul>\n<li>Keys that hash to the old bucket index still hash there</li>\n<li>Keys that need the newly available high bit go to <code>oldBucketIndex + oldBucketCount</code></li>\n</ul>\n<p>This incremental approach prevents &#34;stop-the-world&#34; pauses. Even with millions of entries, each individual operation only pays a small, bounded cost for evacuation. The map remains responsive throughout the growth process.</p>\n<!-- ## Special Cases and Optimizations\n\n### A note on special tophash values\n\nThe `tophash` array is doing double duty. Not only does it store the top 8 bits of hash values for quick comparisons, but it also uses special marker values to track the state of each slot in the bucket. These markers are crucial for map operations, especially during growth.\n\nThe special values (0-4) are:\n\n- **`emptyRest` (0)**: This cell is empty, and there are no more non-empty cells at higher indexes or overflows. This is an optimization, when Go sees this marker, it knows it can stop scanning the bucket immediately.\n- **`emptyOne` (1)**: This cell is empty, but there might be more entries after it. Go has to keep scanning.\n- **`evacuatedX` (2)**: During growth, this key/value has been evacuated to the first half of the larger table (same bucket index).\n- **`evacuatedY` (3)**: During growth, this key/value has been evacuated to the second half of the larger table (old bucket index + old bucket count).\n- **`evacuatedEmpty` (4)**: This cell was empty when the bucket was evacuated.\n- **`minTopHash` (5)**: Minimum value for a normal filled cell.\n\nNormal tophash values always start at 5 or higher. But what if the top 8 bits of your key's hash are actually 0, 1, 2, 3, or 4?\n\n> If the top 8 bits of a hash compute to less than 5, Go adds `minTopHash` (5) to ensure it doesn't conflict with special markers. For example, if the top 8 bits are `0x03`, Go stores `0x08` instead. During lookup, Go knows to check both the exact tophash and the adjusted value. This clever design allows the tophash array to serve dual purposes: tracking cell states and storing hash bits for quick comparison.\n\nThese markers are why Go can efficiently handle map growth, deletions, and lookups even when the map is in a transitional state. -->\n<h2 id=\"a-note-on-interface-maps\">A Note on interface Maps</h2>\n<p>Maps with <code>interface{}</code> (or <code>any</code>) values are interesting because Go doesn&#39;t know the size of the values at compile time. An <code>interface{}</code> can hold anything: an <code>int</code> (which might be 8 bytes), a <code>string</code> (which is 16 bytes: pointer + length), or a complex struct.</p>\n<p>Let&#39;s see an example:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">data</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd;font-style:italic\">interface</span><span style=\"\">{})</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\"></span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;number&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">42</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;text&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;hello&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\"></span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;slice&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">{</span><span style=\"color:#bd93f9\">1</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">3</span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>How does Go handle this? The values stored in the bucket aren&#39;t the actual data, they&#39;re <strong>interface values</strong>, which are represented with two pointers in runtime: one for the type, and one for the value. This means Go can still calculate a fixed bucket layout even though the concrete types can change.</p>\n<p><mapview name=\"data map[string]interface{}\" buckets=\"4\" items=\"number:42,text:hello,slice:[1 2 3]\" theme=\"purple\" valuetype=\"interface{}\"></mapview></p>\n<p>The actual data (<code>42</code>, <code>&#34;hello&#34;</code>, and the <code>[]int{1, 2, 3}</code> slice) is stored elsewhere in memory, and the interface values in the bucket point to them. This adds a level of abstraction, which is why interface maps can be slightly slower than maps with concrete types.</p>\n<!-- ### A note on deletion\n\nWhen you delete a key from a map using the `delete` built-in function, Go doesn't physically remove the entry or shift other entries around. Instead, it marks the slot as empty by setting the `tophash` to `emptyOne` (or `emptyRest` if there are no more entries after it).\n\n```go\ndelete(userAges, \"bob\")\n```\n\nLet's trace through what happens:\n\n**Step 1: Find the key**\n\nGo hashes \"bob\" and searches through the appropriate bucket (and any overflow buckets) to find the entry.\n\n**Step 2: Clear the slot**\n\nWhen found, Go clears the tophash entry, marking it as empty. The key and value might still be there in memory, but with the tophash cleared, Go will skip over this slot during lookups.\n\n**Step 3: Update count**\n\nThe map's `count` field is decremented.\n\nThe bucket might look like this after deletion:\n\n<MapBucket \n    bucket=\"0\" \n    tophash=\"ab,00,ef,00,00,00,00,00\"\n    keys=\"alice,,carol,,,,,,\"\n    values=\"25,,28,,,,,,\"\n    deleted=\"bob\"\n    theme=\"red\"\n/>\n\nNotice slot 1 is now empty (tophash = 0x00), but \"alice\" and \"carol\" remain in their original positions.\n\n> Why doesn't Go immediately reclaim the space when deleting keys?\n\nMarking slots as empty is much faster than reorganizing the bucket. Imagine if Go had to shift all subsequent entries down by one position after every deletion, that would be expensive! The space can be reused when new key-value pairs are added later, and the bucket structure remains stable without costly compaction.\n\nIf you delete many keys and the map ends up with lots of empty slots and overflow buckets but few actual entries, Go might trigger a same-size growth to compact the data and reclaim wasted space. -->\n<h2 id=\"map-safety-and-concurrency\">Map Safety and Concurrency</h2>\n<p>Here&#39;s something crucial to understand if you&#39;re writing concurrent Go code: <strong>maps are not safe for concurrent access</strong>.</p>\n<p>There are two specific panics in Go runtime:</p>\n<ul>\n<li>When one goroutine tries to read from a map while another goroutine writes, Go will panic with <code>&#34;concurrent map read and map write&#34;</code></li>\n<li>When two or more goroutines try to write to the same map simultaneously, Go will panic with <code>&#34;concurrent map writes&#34;</code></li>\n</ul>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">// UNSAFE - Will cause fatal error\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">m</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1000</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">        </span><span style=\"\">m</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;key&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#6272a4\">// Write\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\"></span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1000</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">        </span><span style=\"\">_</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">m</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;key&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"color:#6272a4\">// Read\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\"></span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1000</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">2000</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">        </span><span style=\"\">m</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;key&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#6272a4\">// Write again\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\"></span><span style=\"\">}()</span><span style=\"\">\n</span></span></span></code></pre><p>This code will likely crash within the first few iterations.</p>\n<p>Notice that concurrent reading only in a map is not a panic-invoking action. However most of the time you will need to use maps for both read and write in different goroutines concurrently.</p>\n<p><strong>Solution</strong>: Use <code>sync.Map</code>, mutex protection, or channels to coordinate access!</p>\n<h3 id=\"how-to-make-maps-safe-for-concurrent-use\">How to Make Maps Safe for Concurrent Use</h3>\n<p>The most common solution is to protect the map with a <code>sync.Mutex</code>:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">// SAFE - Using sync.Mutex\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">mu</span><span style=\"\"> </span><span style=\"\">sync</span><span style=\"\">.</span><span style=\"\">Mutex</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\"></span><span style=\"\">m</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\"></span><span style=\"color:#6272a4\">// Writer goroutine\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1000</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">        </span><span style=\"\">mu</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Lock</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">        </span><span style=\"\">m</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;key&#34;</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">        </span><span style=\"\">mu</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Unlock</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\"></span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\"></span><span style=\"color:#6272a4\">// Reader goroutine\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1000</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">        </span><span style=\"\">mu</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Lock</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">        </span><span style=\"\">_</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">m</span><span style=\"\">[</span><span style=\"color:#f1fa8c\">&#34;key&#34;</span><span style=\"\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">        </span><span style=\"\">mu</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Unlock</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\"></span><span style=\"\">}()</span><span style=\"\">\n</span></span></span></code></pre><p>By holding the lock using <code>mu.Lock()</code> before entering the critical sections, we ensure only one goroutine accesses the map at a time.</p>\n<p>We can also use <code>defer</code> to automatically release the lock at the return of the goroutine. This is also a well-known pattern in Go:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">// SAFE - Using sync.Mutex with defer\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">writer</span><span style=\"\">(</span><span style=\"\">m</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">mu</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">sync</span><span style=\"\">.</span><span style=\"\">Mutex</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">start</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">stop</span><span style=\"\"> </span><span style=\"color:#8be9fd\">int</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"\">mu</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Lock</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">mu</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Unlock</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"color:#6272a4\">// This function will be called right before the return\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">start</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"\">stop</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">        </span><span style=\"\">key</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sprintf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;key-%d&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">        </span><span style=\"\">m</span><span style=\"\">[</span><span style=\"\">key</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">mu</span><span style=\"\"> </span><span style=\"\">sync</span><span style=\"\">.</span><span style=\"\">Mutex</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\"></span><span style=\"\">m</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\"></span><span style=\"color:#6272a4\">// Writer goroutines\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#50fa7b\">writer</span><span style=\"\">(</span><span style=\"\">m</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">mu</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#50fa7b\">writer</span><span style=\"\">(</span><span style=\"\">m</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">mu</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">200</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#50fa7b\">writer</span><span style=\"\">(</span><span style=\"\">m</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">mu</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">200</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">300</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p>For read-heavy workloads, you can use <code>sync.RWMutex</code> to allow multiple concurrent readers (but still only one writer at a time). For specialized use cases, <code>sync.Map</code> provides a concurrent map implementation optimized for specific access patterns.</p>\n<!-- \n> Why didn't Go make maps thread-safe by default?\n\nMaking maps thread-safe would add locking overhead to every single map operation, even in single-threaded code (the vast majority of map usage). This goes against Go's philosophy of \"you don't pay for what you don't use.\" If you need concurrency, you add explicit synchronization, making the cost visible and giving you control over the synchronization strategy (mutex, RWMutex, channels, sync.Map, etc.). -->\n<!-- ## Map Iteration Behavior\n\nHere's something that surprises many new Go developers: when you iterate over a map, the order is **intentionally randomized**. Run the same program twice, and you'll get different iteration orders:\n\n```go\nm := map[string]int{\"alice\": 25, \"bob\": 30, \"carol\": 28}\n\n// Iteration order is random and changes between runs!\nfor name, age := range m {\n    fmt.Printf(\"%s is %d years old\\n\", name, age)\n}\n// Output order might be: bob, alice, carol\n// Next run might be: carol, bob, alice  \n// Next run might be: alice, carol, bob\n```\n\nThis isn't a quirk or a bug. Go **deliberately** randomizes the iteration order on every run. Why would Go do this?\n\n> The Go runtime deliberately randomizes map iteration order by starting from a random bucket and wrapping around. This design choice catches bugs early where code incorrectly assumes a specific iteration order.\n\n### Why Randomize?\n\nThe randomization serves several important purposes:\n\n**1. Prevents brittle code**\n\nIf iteration order were consistent (even if unspecified), developers would inevitably write code that depends on it. Tests would pass, code would ship, and then a future Go version might change the internal implementation, breaking \"working\" code.\n\n**2. Makes bugs surface immediately**\n\nOrder-dependent bugs show up during development, not in production. If your code works one run and fails the next, you know you have a problem with assuming order.\n\n**3. Future-proofs the language**\n\nBy making order explicitly random, Go can change map implementations (like the upcoming swiss tables) without worrying about breaking code that accidentally relied on iteration order.\n\nThe randomization happens by picking a random starting bucket on each iteration, then iterating through buckets in sequence (wrapping around at the end). This means all buckets get visited, just in an unpredictable order.\n\n### Getting Ordered Iteration\n\nIf you need ordered output, sort the keys first:\n\n```go\nkeys := make([]string, 0, len(m))\nfor k := range m {\n    keys = append(keys, k)\n}\nsort.Strings(keys)\n\nfor _, k := range keys {\n    fmt.Printf(\"%s: %d\\n\", k, m[k])\n}\n``` -->\n<h2 id=\"comparing-maps-and-slices\">Comparing Maps and Slices</h2>\n<p>Now that we&#39;ve explored both slices and maps in detail, let&#39;s compare these two fundamental Go data structures. While they both store collections of data, they&#39;re designed for very different use cases.</p>\n<table>\n<thead>\n<tr>\n<th>Feature</th>\n<th>Slices</th>\n<th>Maps</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Index Type</strong></td>\n<td>Integer only</td>\n<td>Any comparable type</td>\n</tr>\n<tr>\n<td><strong>Ordering</strong></td>\n<td>Ordered by index</td>\n<td>No guaranteed order</td>\n</tr>\n<tr>\n<td><strong>Growth</strong></td>\n<td>Append to end</td>\n<td>Hash-based placement</td>\n</tr>\n<tr>\n<td><strong>Memory Layout</strong></td>\n<td>Contiguous array</td>\n<td>Hash table with buckets</td>\n</tr>\n<tr>\n<td><strong>Lookup Time</strong></td>\n<td>O(1) by index</td>\n<td>O(1) average by key</td>\n</tr>\n<tr>\n<td><strong>Concurrent Access</strong></td>\n<td>Safe for read-only</td>\n<td>Safe for read-only</td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"when-to-use-slices\">When to use slices</h3>\n<ul>\n<li>You need ordered data with integer indices</li>\n<li>You&#39;re building a list or queue</li>\n<li>You need to iterate in a specific order</li>\n<li>Memory locality matters (more cache-friendly)</li>\n</ul>\n<h3 id=\"when-to-use-maps\">When to use maps</h3>\n<ul>\n<li>You need to look up values by non-integer keys</li>\n<li>Order doesn&#39;t matter</li>\n<li>You need fast membership checks</li>\n<li>You&#39;re building a cache or index</li>\n</ul>\n<blockquote data-quote-character=\"sazak-explain\" class=\"quote-character\"><p> Both slices and maps grow dynamically, but maps are more complex internally due to hash collision handling and bucket management. Slices give you predictable iteration order, while maps give you flexible key types.</p>\n</blockquote>\n<!-- ## Exercises\n\nLet's test your understanding with some hands-on exercises:\n\n<gocodequestion difficulty=\"easy\" playlink=\"\" parsetextfrom=\"questions/visual-go-maps/01.md\">\n    The map starts with 10 key-value pairs. Expression m[\"key5\"] returns 10 (5 * 2). After deletion, the key no longer exists, so the zero value (0) is returned along with false for the existence check.\n</gocodequestion>\n\n<gocodequestion difficulty=\"medium\" playlink=\"\" parsetextfrom=\"questions/visual-go-maps/02.md\">\nMap growth happens internally based on load factor, not at predictable intervals like slice capacity doubling. The hash table likely grows when the average number of items per bucket exceeds 6.5. Unlike slices, maps don't expose their internal bucket count, so we can only observe the number of key-value pairs (len(m)).<br><br>The output will show increasing length values:\n<ul>\n<li>After 1 insertions, len=1</li>\n<li>After 6 insertions, len=6</li>\n<li>After 11 insertions, len=11</li>\n<li>After 16 insertions, len=16</li>\n<li>Final length: 20</li>\n</ul>\n</gocodequestion> -->\n<!-- > In the next article in the Go Internals series, we'll see how atomics work in the background, including a look at the machine instruction level. Stay tuned! -->\n<h2 id=\"references\">References</h2>\n<ul>\n<li><a href=\"https://github.com/golang/go/blob/master/src/runtime/map.go\" target=\"_blank\">Go runtime: <code>runtime/map.go</code> (map internals)</a></li>\n<li><a href=\"https://www.youtube.com/watch?v=Tl7mi9QmLns\" target=\"_blank\">Rob Pike - &#34;Go Maps in Action&#34; (talk)</a></li>\n<li><a href=\"https://go.dev/blog/maps\" target=\"_blank\">The Go Blog - Maps</a></li>\n<li><a href=\"https://go.dev/blog/maps\" target=\"_blank\">The Go Blog - Go maps in action</a></li>\n<li><a href=\"https://go.dev/doc/articles/race_detector\" target=\"_blank\">Data Race Detector</a></li>\n<li><a href=\"https://pkg.go.dev/sync#Map\" target=\"_blank\">sync.Map documentation</a></li>\n<li><a href=\"https://go.dev/ref/mem\" target=\"_blank\">The Go Memory Model</a></li>\n<li><a href=\"https://github.com/golang/go/issues/63438\" target=\"_blank\">Issue #63438: Map load factor clarification</a></li>\n</ul>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr/>\n<ol>\n<li id=\"fn:1\" data-index=\"1\">\n<p>See <a href=\"https://go.dev/blog/comparable\" target=\"_blank\">The Go Blog</a> for more information. <a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:2\" data-index=\"2\">\n<p><a href=\"https://go.dev/doc/faq#references\">https://go.dev/doc/faq#references</a> <a href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:3\" data-index=\"3\">\n<p>The actual hash function used by Go is runtime/aeshash for most types, which uses AES instructions when available for security and performance. Different types may use optimized hash functions (e.g., strings have their own specialized hash). <a href=\"#fnref:3\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:4\" data-index=\"4\">\n<p>The bucket count is always a power of 2, which allows Go to use bitwise operations for bucket selection instead of expensive modulo operations. This is why B represents the power (2^B buckets) rather than the count directly. <a href=\"#fnref:4\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>\n",
            "url": "https://sazak.io/articles/visual-guide-to-go-maps-hash-tables-2025-10-26",
            "title": "Visual Guide to Go Maps: Hash Tables",
            "summary": "This visual guide explores how maps work in Go runtime, covering hash tables, bucket structure, collision handling, and map growth with Go source code.",
            "image": "https://sazak.io/assets/articles/visual-guide-to-go-maps-hash-tables-2025-10-26.jpeg",
            "date_modified": "2025-10-26T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/talks/an-applied-introduction-to-ebpf-with-go-2024-07-18",
            "content_html": "<p>I was at WeAreDevelopers World Congress 2024 in Berlin, Germany. Talked about the basics of eBPF, why you may need to use it, and how to write simple eBPF programs with Go.</p>\n<p>This talk was a polished version of my previous talk at <a href=\"/talks/an-applied-introduction-to-ebpf-with-go-2024-02-17\" target=\"_blank\">GoConf Istanbul 2024</a>.</p>\n",
            "url": "https://sazak.io/talks/an-applied-introduction-to-ebpf-with-go-2024-07-18",
            "title": "An Applied Introduction to eBPF with Go",
            "summary": "I was at WeAreDevelopers World Congress 2024 in Berlin, Germany. I talked about the basics of eBPF, why you may need it, and how to write eBPF programs with Go.",
            "image": "https://sazak.io/assets/talks/an-applied-introduction-to-ebpf-with-go-2024-07-18.jpeg",
            "date_modified": "2024-07-18T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/articles/an-applied-introduction-to-ebpf-with-go-2024-06-06",
            "content_html": "<blockquote>\n<p>This article is from the talk I gave at the <a href=\"/talks/an-applied-introduction-to-ebpf-with-go-2024-02-17\" target=\"_blank\">Go Konf Istanbul &#39;24</a> conference.</p>\n</blockquote>\n<p>Most of the time we are developing software or even using software, we are playing within the safe boundaries of the operating system. We don&#39;t even know how that IP packet was welcomed from the network interface, or those inodes were handled by the filesystem when we save a file.</p>\n<p>That boundary is called the <code>user space</code>, and it&#39;s where we write our applications, libraries, and tools. But there&#39;s another world, which is the <code>kernel space</code>. It&#39;s where the operating system&#39;s kernel resides, and it&#39;s responsible for managing the system&#39;s resources, such as memory, CPU, and I/O devices.</p>\n<p><img src=\"/assets/articles/ebpf-go/arch.png\" alt=\"Operating System Architecture\" loading=\"lazy\"/></p>\n<p>We usually don&#39;t need to go below the sockets or file descriptors, but sometimes we need to. Let&#39;s say you want to profile an application to see how much resource it consumes.</p>\n<p>If you profile the application from the user space, you will not only miss too many useful details, but also you will consume a significant amount of resources for profiling itself, <strong>because each layer on top of the CPU or memory introduces some overhead</strong>.</p>\n<h2 id=\"the-need-to-go-deeper\">The Need to Go Deeper</h2>\n<p>Let&#39;s say you want to go down the stack and somehow insert your custom code into the kernel to profile the application, or to trace the system calls, or to monitor the network packets. How would you do that?</p>\n<p>Traditionally you have two options.</p>\n<h3 id=\"option-1-edit-the-kernel-source-code\">Option 1: Edit the Kernel Source Code</h3>\n<p>If you want to change the Linux kernel source code and then ship the same kernel to you customer&#39;s machine, you will need to convince the Linux kernel community that the change is required. Then, you will need to wait for several years for the new kernel version to be adopted by the Linux distributions.</p>\n<p>This is not a practical approach for most of the cases, and it&#39;s also a little<br/>\nmuch for just profiling an application, or monitoring the network packets.</p>\n<h3 id=\"option-2-write-a-kernel-module\">Option 2: Write a Kernel Module</h3>\n<p>You can write a kernel module, which is a piece of code that can be loaded into the kernel and executed. This is a more practical approach, but it has its own risks and downsides.</p>\n<p>First, you need to write a kernel module, which is not an easy task. Then, you need to maintain it regularly, because the kernel is a living thing, and it changes over time. If you don&#39;t maintain your kernel module, it will be outdated and won&#39;t work with the new kernel versions.</p>\n<p>Second, you are risking corrupting your Linux kernel, because kernel modules don&#39;t have security boundaries. If you write a kernel module that has a bug, it can crash the whole system.</p>\n<h2 id=\"enter-ebpf\">Enter eBPF</h2>\n<p>eBPF (Extended Berkeley Packet Filter) is a revolutionary technology that allows you to <strong>reprogram the Linux kernel within minutes, even without rebooting the system</strong>.</p>\n<p>eBPF allows you to trace system calls, user space functions, library functions, network packets, and much more. It&#39;s a powerful tool for systems performance, monitoring, securtiy, and much more.</p>\n<h3 id=\"but-how\">But how?</h3>\n<p>eBPF is a system consisting of several components:</p>\n<ul>\n<li>eBPF programs</li>\n<li>eBPF hooks</li>\n<li>BPF maps</li>\n<li>eBPF verifier</li>\n<li>The eBPF virtual machine</li>\n</ul>\n<blockquote>\n<p>Note that I have used the term &#34;BPF&#34; and &#34;eBPF&#34; interchangeably. eBPF stands for &#34;Extended Berkeley Packet Filter&#34;. BPF was originally introduced to Linux to filter network packets, but eBPF extends the original BPF to allow it to be used for other purposes. Today it&#39;s not related to Berkeley, and it&#39;s not only for filtering packets.</p>\n</blockquote>\n<p>Below is an illustration of how eBPF works in both user space and under the hood. eBPF programs are written in a high-level language, such as C, and then compiled to <code>eBPF bytecode</code>. Then, the eBPF bytecode is loaded into the kernel and executed by the <code>eBPF virtual machine</code>.</p>\n<p>An eBPF program is attaced to a specific code path in the kernel, such as a system call. These code paths are called <code>&#34;hooks&#34;</code>. When the hook is triggered, the eBPF program is executed and now it performs the custom logic you have written. This way we can run our custom code in the kernel space.</p>\n<p><img src=\"/assets/articles/ebpf-go/ebpf.png\" alt=\"Operating System Architecture\" loading=\"lazy\"/></p>\n<h2 id=\"hello-world-with-ebpf\">Hello World with eBPF</h2>\n<p>Before moving on to the details, let&#39;s write a simple eBPF program to trace the <code>execve</code> system call. We will write the program in C, the user space program in Go, and then run the user space program which will load the eBPF program into the kernel, and poll the custom events we will emit from the eBPF program, right before the actual <code>execve</code> system call is executed.</p>\n<h3 id=\"writing-the-ebpf-program\">Writing the eBPF Program</h3>\n<p>Let&#39;s start writing the eBPF program first. I will write part by part to explain the details better, but you can find the whole program in my GitHub repo: <a href=\"https://github.com/ozansz/intro-ebpf-with-go/tree/main/0x01-helloworld\" target=\"_blank\">ozansz/intro-ebpf-with-go</a>.</p>\n<pre data-filename=\"hello_ebpf.c\" data-language=\"c\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#ff79c6\">#include</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&#34;vmlinux.h&#34;</span><span style=\"color:#ff79c6\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#ff79c6\">#include</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;bpf/bpf_helpers.h&gt;</span><span style=\"color:#ff79c6\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"color:#ff79c6\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">event</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">    </span><span style=\"\">u32</span><span style=\"\"> </span><span style=\"\">pid</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">    </span><span style=\"\">u8</span><span style=\"\">  </span><span style=\"\">comm</span><span style=\"\">[</span><span style=\"color:#bd93f9\">100</span><span style=\"\">];</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\"></span><span style=\"\">};</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">__uint</span><span style=\"\">(</span><span style=\"\">type</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">BPF_MAP_TYPE_RINGBUF</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">__uint</span><span style=\"\">(</span><span style=\"\">max_entries</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1000</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\"> </span><span style=\"\">events</span><span style=\"\"> </span><span style=\"\">SEC</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;.maps&#34;</span><span style=\"\">);</span><span style=\"\">\n</span></span></span></code></pre><p>Here we import the <code>vmlinux.h</code> header file, which contains the kernel&#39;s data structures and function prototypes. Then we include the <code>bpf_helpers.h</code> header file, which contains helper functions for eBPF programs.</p>\n<p>Then we define a <code>struct</code> to hold the event data, and then we define a <a href=\"https://docs.kernel.org/bpf/maps.html\" target=\"_blank\">BPF map</a> to store the events. We will use this map to communicate the events between the eBPF program, which will run in kernel space, and the user space program.</p>\n<blockquote>\n<p>We will go into the details of BPF maps later, so don&#39;t worry if you don&#39;t understand why we used <code>BPF_MAP_TYPE_RINGBUF</code>, or what is <code>SEC(&#34;.maps&#34;)</code> for.</p>\n</blockquote>\n<p>We are now ready to write our first program and define the hook that it will be attached to:</p>\n<pre data-filename=\"hello_ebpf.c\" data-language=\"c\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"\">SEC</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;kprobe/sys_execve&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd\">int</span><span style=\"\"> </span><span style=\"\">hello_execve</span><span style=\"\">(</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">pt_regs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">ctx</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"\">u64</span><span style=\"\"> </span><span style=\"\">id</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">bpf_get_current_pid_tgid</span><span style=\"\">();</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">    </span><span style=\"\">pid_t</span><span style=\"\"> </span><span style=\"\">pid</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">id</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&gt;&gt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">    </span><span style=\"\">pid_t</span><span style=\"\"> </span><span style=\"\">tid</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">u32</span><span style=\"\">)</span><span style=\"\">id</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">pid</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"\">tid</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">event</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">e</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">e</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">bpf_ringbuf_reserve</span><span style=\"\">(</span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">events</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">sizeof</span><span style=\"\">(</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">event</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#ff79c6\">!</span><span style=\"\">e</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">e</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">pid</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">pid</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">bpf_get_current_comm</span><span style=\"\">(</span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">e</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">comm</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">bpf_ringbuf_submit</span><span style=\"\">(</span><span style=\"\">e</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>Here we define a function, <code>hello_execve</code>, and attach it to the <code>sys_execve</code> system call using the <code>kprobe</code> hook. <code>kprobe</code> is one of many hooks that eBPF provides, and it&#39;s used to trace kernel functions. This hook will trigger our <code>hello_execve</code> function right before the <code>sys_execve</code> system call is executed.</p>\n<p>Inside the <code>hello_execve</code> function, we first get the process ID and the thread ID, and then we check if they are the same. If they are not the same, that means we are in a thread, and we don&#39;t want to trace threads, so we exit the eBPF program by returning zero.</p>\n<p>We then reserve space in the <code>events</code> map to store the event data, and then we fill the event data with the process ID and the command name of the process. Then we submit the event to the <code>events</code> map.</p>\n<p>It&#39;s pretty simple until now, right?</p>\n<h3 id=\"writing-the-user-space-program\">Writing the User Space Program</h3>\n<p>Before starting to write the user space program, let me briefly explain what the program needs to do in user space. We need a user space program to load the eBPF program into the kernel, create the BPF map, attach to the BPF map, and then read the events from the BPF map.</p>\n<p>To perform these operations, we need to use a specific system call. This system call is called <code>bpf()</code>, and it&#39;s used to perform several eBPF-related operations, such as reading the contents of a BPF map.</p>\n<p>We can call this system call ourselves from the user space as well, but it means too many low-level operations. Thankfully there are libraries that provide a high-level interface to the <code>bpf()</code> system call. One of them is <a href=\"https://cilium.io/\" target=\"_blank\">Cilium</a>&#39;s <a href=\"github.com/cilium/ebpf\" target=\"_blank\">ebpf-go</a> package, which we will use in this example.</p>\n<p>Let&#39;s dive into some Go code.</p>\n<pre data-filename=\"main.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -type event ebpf hello_ebpf.c\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">main</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">stopper</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"\">Signal</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">signal</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Notify</span><span style=\"\">(</span><span style=\"\">stopper</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"\">Interrupt</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">syscall</span><span style=\"\">.</span><span style=\"\">SIGTERM</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Allow the current process to lock memory for eBPF resources.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">rlimit</span><span style=\"\">.</span><span style=\"color:#50fa7b\">RemoveMemlock</span><span style=\"\">();</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatal</span><span style=\"\">(</span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">objs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">ebpfObjects</span><span style=\"\">{}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">loadEbpfObjects</span><span style=\"\">(</span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">objs</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">);</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;loading objects: %v&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">objs</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">kp</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">link</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Kprobe</span><span style=\"\">(</span><span style=\"\">kprobeFunc</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">objs</span><span style=\"\">.</span><span style=\"\">HelloExecve</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;opening kprobe: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">kp</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">rd</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">ringbuf</span><span style=\"\">.</span><span style=\"color:#50fa7b\">NewReader</span><span style=\"\">(</span><span style=\"\">objs</span><span style=\"\">.</span><span style=\"\">Events</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;opening ringbuf reader: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">rd</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">...</span><span style=\"\">\n</span></span></span></code></pre><p>The first line is a Go compiler directive, <code>go:generate</code>. Here we say to the Go compiler to run the <code>bpf2go</code> tool from the <code>github.com/cilium/ebpf/cmd/bpf2go</code> package, and generate a Go file from the <code>hello_ebpf.c</code> file.</p>\n<p>The generated Go files will include the Go representation of the eBPF program, the types and structs we have defined in the eBPF program, etc. We then will use these representations inside our Go code to load the eBPF program into the kernel, and to interact with the BPF map.</p>\n<p>We then use the generated types to load the eBPF program (<code>loadEbpfObjects</code>), attach to the kprobe hook (<code>link.Kprobe</code>), and read the events from the BPF map (<code>ringbuf.NewReader</code>). All of these functions use the generated types.</p>\n<p>It&#39;s time to interact with the kernel side:</p>\n<pre data-filename=\"main.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">...</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\">stopper</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">rd</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">();</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;closing ringbuf reader: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Println</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;Waiting for events..&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">event</span><span style=\"\"> </span><span style=\"\">ebpfEvent</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">record</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">rd</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Read</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">errors</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Is</span><span style=\"\">(</span><span style=\"\">err</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">ringbuf</span><span style=\"\">.</span><span style=\"\">ErrClosed</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">\t\t\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Println</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;Received signal, exiting..&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">\t\t\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;reading from reader: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">continue</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">binary</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Read</span><span style=\"\">(</span><span style=\"\">bytes</span><span style=\"\">.</span><span style=\"color:#50fa7b\">NewBuffer</span><span style=\"\">(</span><span style=\"\">record</span><span style=\"\">.</span><span style=\"\">RawSample</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"\">binary</span><span style=\"\">.</span><span style=\"\">LittleEndian</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">event</span><span style=\"\">);</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;parsing ringbuf event: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">continue</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">procName</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">unix</span><span style=\"\">.</span><span style=\"color:#50fa7b\">ByteSliceToString</span><span style=\"\">(</span><span style=\"\">event</span><span style=\"\">.</span><span style=\"\">Comm</span><span style=\"\">[:])</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">31</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;pid: %d\\tcomm: %s\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">event</span><span style=\"\">.</span><span style=\"\">Pid</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">procName</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">32</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">33</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>We start a goroutine to listen to the <code>stopper</code> channel, which we defined in the previous Go snippet. This channel will be used to stop the program gracefully when we receive an interrupt signal.</p>\n<p>We then start a loop to read the events from the BPF map. We use the <code>ringbuf.Reader</code> type to read the events, and then we parse the event data using the <code>binary.Read</code> function, into the <code>ebpfEvent</code> type, which is generated from the eBPF program.</p>\n<p>We then print the process ID and the command name of the process to the standard output.</p>\n<h3 id=\"running-the-program\">Running the Program</h3>\n<p>Now we are ready to run the program. First, we need to compile the eBPF program, and then run the user space program.</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">$ go generate\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">Compiled /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x01-helloworld/ebpf_bpfel.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">Stripped /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x01-helloworld/ebpf_bpfel.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">Wrote /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x01-helloworld/ebpf_bpfel.go\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\">Compiled /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x01-helloworld/ebpf_bpfeb.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6</span><span style=\"\"><span style=\"\">Stripped /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x01-helloworld/ebpf_bpfeb.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7</span><span style=\"\"><span style=\"\">Wrote /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x01-helloworld/ebpf_bpfeb.go\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">8</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">9</span><span style=\"\"><span style=\"\">$ go build -o hello_ebpf\n</span></span></span></code></pre><p>We first run the <code>go generate</code> command to compile the eBPF program, and then we run the <code>go build</code> command to compile the user space program.</p>\n<p>Then we run the user space program:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">sudo ./hello_ebpf\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">hello_ebpf: 01:20:54 Waiting </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> events..\n</span></span></span></code></pre><p>I&#39;m running this program inside a VM in <a href=\"https://github.com/lima-vm/lima\" target=\"_blank\">Lima</a>, why not open another shell and see what will happen?</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">limactl shell intro-ebpf\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">$\n</span></span></span></code></pre><p>Meanwhile in the first shell:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3360\tcomm: sshd\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3360\tcomm: bash\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3361\tcomm: bash\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3362\tcomm: bash\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3363\tcomm: bash\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3366\tcomm: bash\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3367\tcomm: lesspipe\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">8</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3369\tcomm: lesspipe\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">9</span><span style=\"\"><span style=\"\">hello_ebpf: 01:22:22 pid: 3370\tcomm: bash\n</span></span></span></code></pre><p>As expected, we are seeing that the <code>sshd</code> process is starting, and then the <code>bash</code> process is starting, and then the <code>lesspipe</code> process is starting, and so on.</p>\n<p>This is a simple example of how we can use eBPF to trace the <code>execve</code> system call, and then read the events from the BPF map in the user space. We wrote a fairly simple yet powerful program, and we intercepted the <code>execve</code> system call without modifying the kernel source code or restarting the system.</p>\n<h2 id=\"ebpf-hooks-and-maps\">eBPF Hooks and Maps</h2>\n<p>So, what actually happened in the previous example? We attached the eBPF program to the <code>sys_execve</code> system call using the <code>kprobe</code> hook, to run the <code>hello_execve</code> function wheneve the <code>sys_execve</code> system call is called, right before the original system call is code is executed.</p>\n<p><img src=\"/assets/articles/ebpf-go/hello-world.png\" alt=\"\" loading=\"lazy\"/></p>\n<p>eBPF is event driven, meaning that it expects us to attach the eBPF program to a specific code path in the kernel. These code paths are called &#34;hooks&#34;, and there are several types of hooks that eBPF provides. The most common ones are:</p>\n<ul>\n<li><code>kprobe</code>, <code>kretprobe</code>: Trace kernel functions</li>\n<li><code>uprobe</code>, <code>uretprobe</code>: Trace user space functions</li>\n<li><code>tracepoint</code>: Trace predefined tracepoints in the kernel</li>\n<li><code>xdp</code>: eXpress Data Path, used to filter and redirect network packets</li>\n<li><code>usdt</code>: User Statically Defined Tracing, used to trace user space functions in a more efficient way</li>\n</ul>\n<p>The hooks <code>kprobe</code> and <code>uprobe</code> are used to invoke the attached eBPF programs <strong>before</strong> the function/syscall execution, and <code>kretprobe</code> and <code>uretprobe</code> are used to invoke the attached eBPF programs <strong>after</strong> the function/syscall execution.</p>\n<p>We also used a BPF map to store the events. BPF maps are data structures to store and communicate different kinds of data. We also use them for state management. There are too many types of BPF maps supported, and we use different types of maps for different purposes. Some of the most common BPF map types are:</p>\n<ul>\n<li><code>BPF_MAP_TYPE_HASH</code>: A hash map</li>\n<li><code>BPF_MAP_TYPE_ARRAY</code>: An array</li>\n<li><code>BPF_MAP_TYPE_RINGBUF</code>: A ring buffer</li>\n<li><code>BPF_MAP_TYPE_STACK</code>: A stack</li>\n<li><code>BPF_MAP_TYPE_QUEUE</code>: A queue</li>\n<li><code>BPF_MAP_TYPE_LRU_HASH</code>: A least recently used hash map</li>\n</ul>\n<p>Some of these map types also have per-CPU variants, such as <code>BPF_MAP_TYPE_PERCPU_HASH</code>, which is a hash map with a separate hash table for each CPU core.</p>\n<h2 id=\"one-step-further-tracing-incoming-ip-packets\">One Step Further: Tracing Incoming IP Packets</h2>\n<p>Let&#39;s take a step further and write a more complex eBPF program. This time we will use the <code>XDP</code> hook to invoke the eBPF program right after the network interface sends a network packet to the kernel, <strong>even before the kernel processes the packet</strong>.</p>\n<p><img src=\"/assets/articles/ebpf-go/xdp.png\" alt=\"\" loading=\"lazy\"/></p>\n<h3 id=\"writing-the-ebpf-program-1\">Writing the eBPF Program</h3>\n<p>We will write an eBPF program to count the number of incoming IP packets by the source IP address and port number, and then we will read the counts from the BPF map in the user space. We will parse the ethernet, IP and TCP/UDP headers of each packet, and store the counts of the valid TCP/UDP packets in the BPF map.</p>\n<p>First, the eBPF program:</p>\n<pre data-filename=\"hello_ebpf.c\" data-language=\"c\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#ff79c6\">#include</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&#34;vmlinux.h&#34;</span><span style=\"color:#ff79c6\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#ff79c6\">#include</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;bpf/bpf_helpers.h&gt;</span><span style=\"color:#ff79c6\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"color:#ff79c6\">#include</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;bpf/bpf_endian.h&gt;</span><span style=\"color:#ff79c6\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"color:#ff79c6\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">#define MAX_MAP_ENTRIES 100\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"color:#ff79c6\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\"></span><span style=\"color:#6272a4\">/* Define an LRU hash map for storing packet count by source IP and port */</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">__uint</span><span style=\"\">(</span><span style=\"\">type</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">BPF_MAP_TYPE_LRU_HASH</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">__uint</span><span style=\"\">(</span><span style=\"\">max_entries</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">MAX_MAP_ENTRIES</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">__type</span><span style=\"\">(</span><span style=\"\">key</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">u64</span><span style=\"\">);</span><span style=\"\"> </span><span style=\"color:#6272a4\">// source IPv4 addresses and port tuple\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"\">__type</span><span style=\"\">(</span><span style=\"\">value</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">u32</span><span style=\"\">);</span><span style=\"\"> </span><span style=\"color:#6272a4\">// packet count\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">}</span><span style=\"\"> </span><span style=\"\">xdp_stats_map</span><span style=\"\"> </span><span style=\"\">SEC</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;.maps&#34;</span><span style=\"\">);</span><span style=\"\">\n</span></span></span></code></pre><p>Like the first example, we will include the <code>vmlinux.h</code> and BPF helper headers. We also define a map, <code>xdp_stats_map</code>, to store the <code>IP:ports</code> and packet count information. We wil then populate this map inside the hook function and read the contents in the user space program.</p>\n<p>What I mean by <code>IP:ports</code> is basically a <code>u64</code> value, packed with the source IP, source port and the destination port. The IP address (<strong>IPv4</strong>, specifically) is 32-bits long, and each port number is 16-bits long, so we need exactly 64 bits to store all three - that&#39;s why we are using <code>u64</code> here. We are only processing the ingress (incoming packets) here so we won&#39;t need to store the destination IP address.</p>\n<p>Different from the last example we now used <code>BPF_MAP_TYPE_LRU_HASH</code> as the map type. This type of map lets us store a <code>(key, value)</code> pair as a hashmap with LRU variant.</p>\n<p>See how we defined the map here, we explicitly set the number of maximum entries, and the types of the map key and values. For key we are using a 64-bit unsigned integer and for value a 32-bit unsigned integer.</p>\n<blockquote>\n<p>The maximum value of <code>u32</code> is <code>2^32 - 1</code>, which is more than enough packets for the sake of this example.</p>\n</blockquote>\n<p>To learn the IP address and port number, we first need to parse the packet and read the <strong>ethernet, IP and then TCP/UDP headers</strong>.</p>\n<p>As XDP is placed right after the network interface card, we will be given the <strong>raw packet data in bytes</strong>, so we will need to manually walk on the byte array and unmarshal the ethernet, IP and TCP/UDP headers.</p>\n<p>Hopefully, we have all the header definitions (<code>struct ethhdr</code>, <code>struct iphdr</code>, <code>struct tcphdr</code>, and <code>struct udphdr</code>),  inside <code>vmlinux.h</code> header file. We will use these structs to extract the IP address and port number information in a separate function, <code>parse_ip_packet</code>:</p>\n<pre data-filename=\"hello_ebpf.c\" data-language=\"c\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#ff79c6\">#define ETH_P_IP\t\t0x0800\t</span><span style=\"color:#6272a4\">/* Internet Protocol packet\t*/</span><span style=\"color:#ff79c6\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#ff79c6\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">#define PARSE_SKIP \t\t\t0\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"color:#ff79c6\">#define PARSED_TCP_PACKET\t1\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"color:#ff79c6\">#define PARSED_UDP_PACKET\t2\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"color:#ff79c6\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">static</span><span style=\"\"> </span><span style=\"\">__always_inline</span><span style=\"\"> </span><span style=\"color:#8be9fd\">int</span><span style=\"\"> </span><span style=\"color:#50fa7b\">parse_ip_packet</span><span style=\"\">(</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">xdp_md</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">ctx</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">u64</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">ip_metadata</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd\">void</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">data_end</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#8be9fd\">void</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">)(</span><span style=\"color:#8be9fd\">long</span><span style=\"\">)</span><span style=\"\">ctx</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">data_end</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd\">void</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">data</span><span style=\"\">     </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#8be9fd\">void</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">)(</span><span style=\"color:#8be9fd\">long</span><span style=\"\">)</span><span style=\"\">ctx</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">data</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// First, parse the ethernet header.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">ethhdr</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">eth</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"color:#8be9fd\">void</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">)(</span><span style=\"\">eth</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&gt;</span><span style=\"\"> </span><span style=\"\">data_end</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">PARSE_SKIP</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">eth</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">h_proto</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"\">bpf_htons</span><span style=\"\">(</span><span style=\"\">ETH_P_IP</span><span style=\"\">))</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#6272a4\">// The protocol is not IPv4, so we can&#39;t parse an IPv4 source address.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">PARSE_SKIP</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Then parse the IP header.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">iphdr</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">ip</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#8be9fd\">void</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">)(</span><span style=\"\">eth</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"color:#8be9fd\">void</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">)(</span><span style=\"\">ip</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&gt;</span><span style=\"\"> </span><span style=\"\">data_end</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">PARSE_SKIP</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">u16</span><span style=\"\"> </span><span style=\"\">src_port</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">dest_port</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd\">int</span><span style=\"\"> </span><span style=\"\">retval</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">31</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">ip</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">protocol</span><span style=\"\"> </span><span style=\"color:#ff79c6\">==</span><span style=\"\"> </span><span style=\"\">IPPROTO_TCP</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">32</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">tcphdr</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">tcp</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#8be9fd\">void</span><span style=\"color:#ff79c6\">*</span><span style=\"\">)</span><span style=\"\">ip</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#ff79c6\">sizeof</span><span style=\"\">(</span><span style=\"color:#ff79c6\">*</span><span style=\"\">ip</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">33</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"color:#8be9fd\">void</span><span style=\"color:#ff79c6\">*</span><span style=\"\">)(</span><span style=\"\">tcp</span><span style=\"color:#ff79c6\">+</span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&gt;</span><span style=\"\"> </span><span style=\"\">data_end</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">34</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">PARSE_SKIP</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">35</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">36</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">src_port</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">bpf_ntohs</span><span style=\"\">(</span><span style=\"\">tcp</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">source</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">37</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">dest_port</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">bpf_ntohs</span><span style=\"\">(</span><span style=\"\">tcp</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">dest</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">38</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">retval</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">PARSED_TCP_PACKET</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">39</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\"> </span><span style=\"color:#ff79c6\">else</span><span style=\"\"> </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">ip</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">protocol</span><span style=\"\"> </span><span style=\"color:#ff79c6\">==</span><span style=\"\"> </span><span style=\"\">IPPROTO_UDP</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">40</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">udphdr</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">udp</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#8be9fd\">void</span><span style=\"color:#ff79c6\">*</span><span style=\"\">)</span><span style=\"\">ip</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#ff79c6\">sizeof</span><span style=\"\">(</span><span style=\"color:#ff79c6\">*</span><span style=\"\">ip</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">41</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"color:#8be9fd\">void</span><span style=\"color:#ff79c6\">*</span><span style=\"\">)(</span><span style=\"\">udp</span><span style=\"color:#ff79c6\">+</span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&gt;</span><span style=\"\"> </span><span style=\"\">data_end</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">42</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">PARSE_SKIP</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">43</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">44</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">src_port</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">bpf_ntohs</span><span style=\"\">(</span><span style=\"\">udp</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">source</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">45</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">dest_port</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">bpf_ntohs</span><span style=\"\">(</span><span style=\"\">udp</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">dest</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">46</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">retval</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">PARSED_UDP_PACKET</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">47</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\"> </span><span style=\"color:#ff79c6\">else</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">48</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#6272a4\">// The protocol is not TCP or UDP, so we can&#39;t parse a source port.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">49</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">PARSE_SKIP</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">50</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">51</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">52</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Return the (source IP, destination IP) tuple in network byte order.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">53</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#6272a4\">// |&lt;-- Source IP: 32 bits --&gt;|&lt;-- Source Port: 16 bits --&gt;&lt;-- Dest Port: 16 bits --&gt;|\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">54</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"color:#ff79c6\">*</span><span style=\"\">ip_metadata</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"\">u64</span><span style=\"\">)(</span><span style=\"\">ip</span><span style=\"color:#ff79c6\">-&gt;</span><span style=\"\">saddr</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">|</span><span style=\"\"> </span><span style=\"\">((</span><span style=\"\">u64</span><span style=\"\">)</span><span style=\"\">src_port</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"\"> </span><span style=\"color:#bd93f9\">16</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">|</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">u64</span><span style=\"\">)</span><span style=\"\">dest_port</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">55</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">retval</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">56</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>The function:</p>\n<ul>\n<li>Checks if the packet has a valid ethernet header, IP header, and TCP or UDP header. These checks are done by using the <code>h_proto</code> of <code>struct ethhdr</code> and <code>protocol</code> of <code>struct iphdr</code>. Each header stores the protocol of the inner packet it wraps.</li>\n<li>Extracts the IP address from the IP header and port number from the TCP/UDP headers and forms an <code>IP:ports</code> tuple inside a 64-bit unsigned integer (<code>u64</code>)</li>\n<li>Returns a code to tell the caller whether the packet is a TCP packet, a UDP packet, or else (<code>PARSE_SKIP</code>)</li>\n</ul>\n<p>Notice the <code>__always_inline</code> at the beginning of the function signature. This tells the compiler to always inline this funcion as static code, which saves us from performing a function call.</p>\n<p>Now it&#39;s time to write the hook function and use <code>parse_ip_packet</code>:</p>\n<pre data-filename=\"hello_ebpf.c\" data-language=\"c\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"\">SEC</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;xdp&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd\">int</span><span style=\"\"> </span><span style=\"\">xdp_prog_func</span><span style=\"\">(</span><span style=\"color:#ff79c6\">struct</span><span style=\"\"> </span><span style=\"\">xdp_md</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">ctx</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">u64</span><span style=\"\"> </span><span style=\"\">ip_meta</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd\">int</span><span style=\"\"> </span><span style=\"\">retval</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">parse_ip_packet</span><span style=\"\">(</span><span style=\"\">ctx</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">ip_meta</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">\t\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">retval</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"\">PARSED_TCP_PACKET</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">XDP_PASS</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">u32</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">pkt_count</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"\">bpf_map_lookup_elem</span><span style=\"\">(</span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">xdp_stats_map</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">ip_meta</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#ff79c6\">!</span><span style=\"\">pkt_count</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#6272a4\">// No entry in the map for this IP tuple yet, so set the initial value to 1.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t\t</span><span style=\"\">u32</span><span style=\"\"> </span><span style=\"\">init_pkt_count</span><span style=\"\"> </span><span style=\"color:#ff79c6\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">bpf_map_update_elem</span><span style=\"\">(</span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">xdp_stats_map</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">ip_meta</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">init_pkt_count</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">BPF_ANY</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\"> </span><span style=\"color:#ff79c6\">else</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#6272a4\">// Entry already exists for this IP tuple,\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t\t</span><span style=\"color:#6272a4\">// so increment it atomically.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t\t</span><span style=\"\">__sync_fetch_and_add</span><span style=\"\">(</span><span style=\"\">pkt_count</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">);</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">XDP_PASS</span><span style=\"\">;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>The <code>xdp_prog_func</code> is fairly simple as we already coded most of the program logic inside <code>parse_ip_packet</code>. What we do here is:</p>\n<ul>\n<li>Parse the packet using <code>parse_ip_packet</code></li>\n<li>Skip counting if it&#39;s not a TCP or UDP packet by returning <code>XDP_PASS</code></li>\n<li>Lookup the <code>IP:ports</code> tuple in BPF map keys using the <code>bpf_map_lookup_elem</code> helper function</li>\n<li>Set the value to one if the <code>IP:ports</code> tuple is seen the first time, else increment it by one. The <code>__sync_fetch_and_add</code> is an LLVM built-in here</li>\n</ul>\n<p>Finally we attach this function to the <code>XDP</code> subsystem by using the <code>SEC(&#34;xdp&#34;)</code> macro.</p>\n<h3 id=\"writing-the-user-space-program-1\">Writing the User Space Program</h3>\n<p>It&#39;s time to dive into Go code again.</p>\n<pre data-filename=\"main.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">//go:generate go run github.com/cilium/ebpf/cmd/bpf2go ebpf xdp.c\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">    </span><span style=\"\">ifaceName</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">flag</span><span style=\"\">.</span><span style=\"color:#50fa7b\">String</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;iface&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;network interface to attach XDP program to&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\"></span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">main</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">SetPrefix</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;packet_count: &#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">SetFlags</span><span style=\"\">(</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"\">Ltime</span><span style=\"\"> </span><span style=\"\">|</span><span style=\"\"> </span><span style=\"\">log</span><span style=\"\">.</span><span style=\"\">Lshortfile</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">    </span><span style=\"\">flag</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Parse</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Subscribe to signals for terminating the program.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"\">stop</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"\">Signal</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">signal</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Notify</span><span style=\"\">(</span><span style=\"\">stop</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"\">Interrupt</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">syscall</span><span style=\"\">.</span><span style=\"\">SIGTERM</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">iface</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">net</span><span style=\"\">.</span><span style=\"color:#50fa7b\">InterfaceByName</span><span style=\"\">(</span><span style=\"color:#ff79c6\">*</span><span style=\"\">ifaceName</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;network iface lookup for %q: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">ifaceName</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Load pre-compiled programs and maps into the kernel.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"\">objs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">ebpfObjects</span><span style=\"\">{}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">loadEbpfObjects</span><span style=\"\">(</span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">objs</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">);</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;loading objects: %v&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">objs</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#6272a4\">// Attach the program.\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"\">\t</span><span style=\"\">l</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">link</span><span style=\"\">.</span><span style=\"color:#50fa7b\">AttachXDP</span><span style=\"\">(</span><span style=\"\">link</span><span style=\"\">.</span><span style=\"\">XDPOptions</span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">Program</span><span style=\"\">:</span><span style=\"\">   </span><span style=\"\">objs</span><span style=\"\">.</span><span style=\"\">XdpProgFunc</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">31</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">Interface</span><span style=\"\">:</span><span style=\"\"> </span><span style=\"\">iface</span><span style=\"\">.</span><span style=\"\">Index</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">32</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">})</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">33</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">34</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;could not attach XDP program: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">35</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">36</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">l</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">37</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">38</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;Attached XDP program to iface %q (index %d)&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">iface</span><span style=\"\">.</span><span style=\"\">Name</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">iface</span><span style=\"\">.</span><span style=\"\">Index</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">39</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">40</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">...</span><span style=\"\">\n</span></span></span></code></pre><p>Here we first load the generated eBPF program and map using the <code>loadEbpfObjects</code> function. Then we attach the program to the specified network interface using the <code>link.AttachXDP</code> function. Similar to the previous example we used a channel to listen to the interrupt signal and close the program gracefully.</p>\n<p>Next, we will read the map contents in every second and print the packet counts to the standard output:</p>\n<pre data-filename=\"main.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">...</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"\">ticker</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">time</span><span style=\"\">.</span><span style=\"color:#50fa7b\">NewTicker</span><span style=\"\">(</span><span style=\"\">time</span><span style=\"\">.</span><span style=\"\">Second</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">ticker</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Stop</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">select</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">case</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\">stop</span><span style=\"\">:</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">objs</span><span style=\"\">.</span><span style=\"\">XdpStatsMap</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">();</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t\t\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Fatalf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;closing map reader: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">case</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\">ticker</span><span style=\"\">.</span><span style=\"\">C</span><span style=\"\">:</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">m</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">parsePacketCounts</span><span style=\"\">(</span><span style=\"\">objs</span><span style=\"\">.</span><span style=\"\">XdpStatsMap</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">excludeIPs</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\t\t\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;Error reading map: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\t\t\t\t</span><span style=\"color:#ff79c6\">continue</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;Map contents:\\n%s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">m</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"\">srv</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Submit</span><span style=\"\">(</span><span style=\"\">m</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>We will use a utility function, <code>parsePacketCounts</code>, to read the map contents and parse the packet counts. This function will read the map contents in a loop.</p>\n<p>As we will be given raw bytes from the map, we will need to parse the bytes and convert them into a human-readable format. We will define a new type <code>PacketCounts</code> to store the parsed map contents.</p>\n<pre data-filename=\"main.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">IPMetadata</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">SrcIP</span><span style=\"\">   </span><span style=\"\">netip</span><span style=\"\">.</span><span style=\"\">Addr</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">SrcPort</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uint16</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">DstPort</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uint16</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">t</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">IPMetadata</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#50fa7b\">UnmarshalBinary</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">byte</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#8be9fd\">error</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">8</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Errorf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;invalid data length: %d&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">t</span><span style=\"\">.</span><span style=\"\">SrcIP</span><span style=\"\">.</span><span style=\"color:#50fa7b\">UnmarshalBinary</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#bd93f9\">4</span><span style=\"\">:</span><span style=\"color:#bd93f9\">8</span><span style=\"\">]);</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">t</span><span style=\"\">.</span><span style=\"\">SrcPort</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">uint16</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#bd93f9\">3</span><span style=\"\">])</span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"color:#bd93f9\">8</span><span style=\"\"> </span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">uint16</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#bd93f9\">2</span><span style=\"\">])</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">t</span><span style=\"\">.</span><span style=\"\">DstPort</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">uint16</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#bd93f9\">1</span><span style=\"\">])</span><span style=\"color:#ff79c6\">&lt;&lt;</span><span style=\"color:#bd93f9\">8</span><span style=\"\"> </span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">uint16</span><span style=\"\">(</span><span style=\"\">data</span><span style=\"\">[</span><span style=\"color:#bd93f9\">0</span><span style=\"\">])</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">t</span><span style=\"\"> </span><span style=\"\">IPMetadata</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#50fa7b\">String</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sprintf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s:%d =&gt; :%d&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">t</span><span style=\"\">.</span><span style=\"\">SrcIP</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">t</span><span style=\"\">.</span><span style=\"\">SrcPort</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">t</span><span style=\"\">.</span><span style=\"\">DstPort</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">PacketCounts</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">PacketCounts</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#50fa7b\">String</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">keys</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">string</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">k</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">keys</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">keys</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">k</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">sort</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Strings</span><span style=\"\">(</span><span style=\"\">keys</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">31</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">32</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">sb</span><span style=\"\"> </span><span style=\"\">strings</span><span style=\"\">.</span><span style=\"\">Builder</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">33</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">_</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">k</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">keys</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">34</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">sb</span><span style=\"\">.</span><span style=\"color:#50fa7b\">WriteString</span><span style=\"\">(</span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sprintf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s\\t| %d\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">k</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\">[</span><span style=\"\">k</span><span style=\"\">]))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">35</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">36</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">37</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">sb</span><span style=\"\">.</span><span style=\"color:#50fa7b\">String</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">38</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>We defined a new type, <code>IPMetadata</code>, to store the <code>IP:ports</code> tuple. We also defined a <code>UnmarshalBinary</code> method to parse the raw bytes and convert them into a human-readable format. We also defined a <code>String</code> method to print the <code>IP:ports</code> tuple in a human-readable format.</p>\n<p>We then defined a new type, <code>PacketCounts</code>, to store the parsed map contents. We also defined a <code>String</code> method to print the map contents in a human-readable format.</p>\n<p>Finally, we will use the <code>PacketCounts</code> type to parse the map contents and print the packet counts:</p>\n<pre data-filename=\"main.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">parsePacketCounts</span><span style=\"\">(</span><span style=\"\">m</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">ebpf</span><span style=\"\">.</span><span style=\"\">Map</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">excludeIPs</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">bool</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">PacketCounts</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd\">error</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">key</span><span style=\"\">    </span><span style=\"\">IPMetadata</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">val</span><span style=\"\">    </span><span style=\"color:#8be9fd\">uint32</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">counts</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"\">PacketCounts</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">iter</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">m</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Iterate</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">iter</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Next</span><span style=\"\">(</span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">key</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">val</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">_</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">excludeIPs</span><span style=\"\">[</span><span style=\"\">key</span><span style=\"\">.</span><span style=\"\">SrcIP</span><span style=\"\">.</span><span style=\"color:#50fa7b\">String</span><span style=\"\">()];</span><span style=\"\"> </span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t\t\t</span><span style=\"color:#ff79c6\">continue</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\t\t</span><span style=\"\">counts</span><span style=\"\">[</span><span style=\"\">key</span><span style=\"\">.</span><span style=\"color:#50fa7b\">String</span><span style=\"\">()]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">int</span><span style=\"\">(</span><span style=\"\">val</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\t</span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">counts</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">iter</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Err</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><h3 id=\"running-the-program-1\">Running the Program</h3>\n<p>We first need to compile the eBPF program and then run the user space program.</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">$ go generate\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">Compiled /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x03-packet-count/ebpf_bpfel.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">Stripped /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x03-packet-count/ebpf_bpfel.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">Wrote /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x03-packet-count/ebpf_bpfel.go\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\">Compiled /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x03-packet-count/ebpf_bpfeb.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6</span><span style=\"\"><span style=\"\">Stripped /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x03-packet-count/ebpf_bpfeb.o\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7</span><span style=\"\"><span style=\"\">Wrote /Users/sazak/workspace/gocode/src/github.com/ozansz/intro-ebpf-with-go/0x03-packet-count/ebpf_bpfeb.go\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">8</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">9</span><span style=\"\"><span style=\"\">$ go build -o packet_count\n</span></span></span></code></pre><p>Now we can run it:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">$ sudo ./packet_count --iface eth0\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">packet_count: 22:11:10 main.go:107: Attached XDP program to iface </span><span style=\"color:#f1fa8c\">&#34;eth0&#34;</span><span style=\"\"> </span><span style=\"color:#ff79c6\">(</span><span style=\"\">index 2</span><span style=\"color:#ff79c6\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">packet_count: 22:11:10 main.go:132: Map contents:\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">192.168.5.2:58597 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :22\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">51</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\">packet_count: 22:11:11 main.go:132: Map contents:\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6</span><span style=\"\"><span style=\"\">192.168.5.2:58597 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :22\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">52</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7</span><span style=\"\"><span style=\"\">packet_count: 22:11:11 main.go:132: Map contents:\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">8</span><span style=\"\"><span style=\"\">192.168.5.2:58597 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :22\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">53</span><span style=\"\">\n</span></span></span></code></pre><p>The packets coming to the port <code>22</code> from the IP address <code>192.168.5.2</code> are the SSH packets, as I am running this program inside a VM and I am SSHing into.</p>\n<p>Let&#39;s run <code>curl</code> inside the VM in another terminal, and see what will happen:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">$ curl https://www.google.com/\n</span></span></span></code></pre><p>Meanwhile in the first terminal:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"\">packet_count: 22:14:07 main.go:132: Map contents:\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">172.217.22.36:443 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :38324\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">12</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">192.168.5.2:58597 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :22\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">551</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">packet_count: 22:14:08 main.go:132: Map contents:\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">172.217.22.36:443 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :38324\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">12</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">192.168.5.2:58597 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :22\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">552</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">packet_count: 22:14:08 main.go:132: Map contents:\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">172.217.22.36:443 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :38324\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">30</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">192.168.5.2:58597 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :22\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">570</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">packet_count: 22:14:09 main.go:132: Map contents:\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">172.217.22.36:443 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :38324\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">30</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">192.168.5.2:58597 </span><span style=\"color:#ff79c6\">=</span><span style=\"\">&gt; :22\t</span><span style=\"\">|</span><span style=\"\"> </span><span style=\"color:#bd93f9\">571</span><span style=\"\">\n</span></span></span></code></pre><p>We are seeing the packets coming to the port <code>38324</code> from the IP address <code>172.217.22.36</code> are the packets coming from the <code>curl</code> command.</p>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>eBPF is powerful in many ways and I think it&#39;s a good technology to invest time in, especially you are in systems programming, observability or security. In this article we have seen what eBPF is, how it works, and how we can start using it with Go.</p>\n<p>I hope you enjoyed this article and learned something new. If you have any questions, feel free to <a href=\"https://twitter.com/oznszk\" target=\"_blank\">ping</a> me.</p>\n<h2 id=\"resources\">Resources</h2>\n<ul>\n<li>Systems Performance, Brendan Gregg</li>\n<li>Learning eBPF, Liz Rice</li>\n<li>docs.kernel.org</li>\n<li>ebpf.io</li>\n<li>cilium.io</li>\n<li>iovisor.org</li>\n<li>brendangregg.com</li>\n</ul>\n",
            "url": "https://sazak.io/articles/an-applied-introduction-to-ebpf-with-go-2024-06-06",
            "title": "An Applied Introduction to eBPF with Go",
            "summary": "eBPF is a revolutionary technology that allows you to reprogram the Linux kernel within minutes, even without rebooting the system. It allows you to trace system calls, user space functions, library functions, network packets, and much more.",
            "image": "https://sazak.io/assets/articles/an-applied-introduction-to-ebpf-with-go-2024-06-06.jpeg",
            "date_modified": "2024-06-06T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/reading-groups/distributed-paper-stacks-2024-04-30",
            "content_html": "<p>Distributed Paper Stacks is the second iteration of Reading Stacks, a tech book reading club we started with a few friends from METU. We meet every two weeks to discuss a distributed systems paper.</p>\n<h2 id=\"schedule\">Schedule</h2>\n<ul>\n<li>Distributed Queues - Can Toraman, May 15</li>\n<li>Dynamo Paper (2007): Distributed Key-Value Stores - Ozann Sazak, May 29</li>\n<li>Realtime State Sharing with CRDTs - Alperen Keles and Ozan Akin, June 12</li>\n<li>Tail Latency in Distributed Systems - Yigit Varli, June 26</li>\n</ul>\n<h2 id=\"organizers\">Organizers</h2>\n<p>We are a group of friends from METU, Turkey.</p>\n<ul>\n<li><a href=\"https://twitter.com/Keleesssss\" target=\"_blank\">Alperen Keleş</a></li>\n<li><a href=\"https://twitter.com/cantoramann\" target=\"_blank\">Can Toraman</a></li>\n<li><a href=\"https://twitter.com/ozn_akn\" target=\"_blank\">Ozan Akın</a></li>\n<li><a href=\"https://twitter.com/oznszk\" target=\"_blank\">Ozan Sazak (me 👋)</a></li>\n<li><a href=\"https://twitter.com/yigit_v4rli\" target=\"_blank\">Yiğit Varlı</a></li>\n</ul>\n",
            "url": "https://sazak.io/reading-groups/distributed-paper-stacks-2024-04-30",
            "title": "Distributed Paper Stacks",
            "summary": "We are oranizing the second iteration of Reading Stacks by reading a distributed systems paper bi-weekly.",
            "date_modified": "2024-04-30T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/talks/homeops-building-a-gitops-driven-homelab-infrastructure-from-scratch-2024-04-20",
            "content_html": "",
            "url": "https://sazak.io/talks/homeops-building-a-gitops-driven-homelab-infrastructure-from-scratch-2024-04-20",
            "title": "HomeOps: Building a GitOps-driven Homelab Infrastructure From Scratch",
            "summary": "I gave an ignite talk at DevOpsDays Istanbul 2024 about building a GitOps-driven homelab infrastructure from scratch, which tools you can use, and how you can automate everything.",
            "image": "https://sazak.io/assets/talks/homeops-building-a-gitops-driven-homelab-infrastructure-from-scratch-2024-04-20.jpeg",
            "date_modified": "2024-04-20T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/talks/openfaas-for-the-curious-hows-and-whys-2024-04-16",
            "content_html": "",
            "url": "https://sazak.io/talks/openfaas-for-the-curious-hows-and-whys-2024-04-16",
            "title": "OpenFaaS for the Curious: How's and Why's",
            "summary": "I talked at a local cloud meetup about starting with OpenFaaS, the internals of OpenFaaS runtimes, and showcased a demo on setting up OpenFaaS on Kubernetes.",
            "image": "https://sazak.io/assets/talks/openfaas-for-the-curious-hows-and-whys-2024-04-16.jpeg",
            "date_modified": "2024-04-16T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/articles/visual-guide-to-slices-in-go-2024-03-25",
            "content_html": "<p>We use slices everywhere in Go. With maps, they are fundamental data types we use to store data. Today we will dive into the internals and see <strong>how slices work under the hood</strong>.</p>\n<blockquote data-quote-character=\"sazak-explain\" class=\"quote-character\"><p> At the end of the article, you will find <a href=\"#exercises\">exercises</a> to test your knowledge. Enjoy!</p>\n</blockquote>\n<h2 id=\"what-is-a-slice\">What is a slice?</h2>\n<p>In Go, <strong>slice is an abstraction over arrays</strong>. It consists of a pointer to the backing array, the length of the slice, and its capacity. The length is the <strong>number of elements in the slice</strong>, while the capacity is the <strong>number of elements in the underlying array</strong>.</p>\n<p>Here&#39;s how a slice is defined in <a href=\"https://github.com/golang/go/blob/cff7267e0d77f02d582c613c272b6f8ebf1c0412/src/runtime/slice.go#L15\" target=\"_blank\">Go runtime</a>:</p>\n<pre data-filename=\"go/src/runtime/slice.go\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">slice</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">array</span><span style=\"\"> </span><span style=\"\">unsafe</span><span style=\"\">.</span><span style=\"\">Pointer</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">len</span><span style=\"\">   </span><span style=\"color:#8be9fd\">int</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">cap</span><span style=\"\">   </span><span style=\"color:#8be9fd\">int</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>The <code>array</code> field is a pointer to the (first element of the) backing array. The <code>len</code> field is the length of the slice, denoting the number of items in the slice, and the <code>cap</code> field is the capacity of the slice. Capacity stores the number of elements in the backing array, and it is the maximum number of elements the slice can hold without reallocating the backing array.</p>\n<p>There are multiple ways to create a slice, and some of them differ in how they set the length and capacity of the slice. Let&#39;s say we have the following slice definition:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s1</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">int32</span><span style=\"\">{</span><span style=\"color:#bd93f9\">1</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">3</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">4</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">5</span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>This creates an <code>int32</code> slice <code>s1</code> with some initial values. The length of the slice is 5, as you can see from the number of elements in the slice definition. The capacity is also set to 5 by default (we did not specify a different capacity), and the backing array is filled with the given values.</p>\n<p>Below is how the backing array looks like in memory. Numbers inside the cells represent values of items in the array, and the gray cells represent the memory that does not belong to the slice. See how both length and capacity is <code>5</code>, and slice points (ptr = <code>0x0100</code>) at the address of the first element of the array (<code>0x0100</code>).</p>\n<p><goslice name=\"s1 []int32\" cap=\"5\" items=\"1,2,3,4,5\" ptr=\"0x0100\" startaddress=\"0x0100\" bytesperblock=\"4\"></goslice></p>\n<h2 id=\"make-ing-of-a-slice\"><code>make</code>-ing of a slice</h2>\n<p>We can specify different lengths and capacities for a slice by using the <code>make</code> built-in function. The <code>make</code> function accepts two to three arguments for slice allocation: the type of the slice, the length, and the capacity. If the capacity is not given, <strong>it defaults to the length</strong>.</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s2</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">([]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">5</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">10</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p>The code above allocates a 10-capacity array and creates a slice <code>s2</code>, which points to this array with a length of 5. The capacity of the slice is also set to 10.</p>\n<p><code>make</code> also fills the array with the <strong>zero values</strong><sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> of the item type. In this case, the zero value of <code>int</code> is <code>0</code>.</p>\n<p><goslice name=\"s2 []int\" cap=\"10\" ptr=\"0x1234\" items=\"0,0,0,0,0\" show-unused-as-zero=\"1\"></goslice></p>\n<blockquote data-quote-character=\"sazak-explain\" class=\"quote-character\"><p> Notice that all items of the backing array are filled with zero values, not only the <code>len</code> items of the slice. From now on I won&#39;t show the zeroes in the unused parts of the backing array to keep the visuals more readable.</p>\n</blockquote>\n<p>If we want to populate this slice with some values, we can set specific indexes:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">s2</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">s2</span><span style=\"\">[</span><span style=\"\">i</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\"> </span><span style=\"color:#bd93f9\">2</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>This will set the values of the slice to <strong>0, 2, 4, 6, 8</strong>, by using <code>range</code><sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup> to iterate over the indexes of the slice.</p>\n<p><goslice name=\"s2 []int\" cap=\"10\" ptr=\"0x1234\" items=\"0,2,4,6,8\" hidelegend=\"1\"></goslice></p>\n<p>Notice how the slice is still pointing to the same underlying array, but the initial values are changed. Also the length and capacity of the slice are still the same.</p>\n<blockquote data-quote-character=\"beaver-question\" class=\"quote-character\"><p> Why didn&#39;t <code>range</code> iterate over all indexes within the capacity (10) of the array?</p>\n</blockquote>\n<p>Good question. Let&#39;s see what happens if we try to set a value to an index that is out of the slice&#39;s length?</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s2</span><span style=\"\">[</span><span style=\"color:#bd93f9\">8</span><span style=\"\">]</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">16</span><span style=\"\">\n</span></span></span></code></pre><p>If we run the assignment above, Go runtime will panic with the message below:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">panic: runtime error: index out of range </span><span style=\"color:#ff79c6\">[</span><span style=\"\">8</span><span style=\"color:#ff79c6\">]</span><span style=\"\"> with length </span><span style=\"color:#bd93f9\">5</span><span style=\"\">\n</span></span></span></code></pre><p>The capacity is not the space Go gives us to use, it&#39;s the maximum number of the elements slice can hold <strong>without reallocating the backing array</strong>. If we try to access or set a value to an index that is out of the slice&#39;s length, Go will panic.</p>\n<p>Okay, so what if we add more elements by simply <code>append</code>ing them to the slice?</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s2</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">int</span><span style=\"\">{</span><span style=\"color:#bd93f9\">10</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">12</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">14</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">16</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">18</span><span style=\"\">}</span><span style=\"color:#ff79c6\">...</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p>The built-in function <code>append</code> works by pushing these items to the end of the slice, starting by the <code>len</code>-th item. Both the length and the capacity of the slice are <strong>10</strong> now.</p>\n<p><goslice name=\"s2 []int\" cap=\"10\" items=\"0,2,4,6,8,10,12,14,16,18\" hidelegend=\"1\"></goslice></p>\n<h2 id=\"growing-the-slice\">Growing the slice</h2>\n<p>What do you think will happen if we add one more item to the end of the slice now, as it&#39;s capacity is already full?</p>\n<p>If we have a full slice (<code>len</code> == <code>cap</code>), then Go runtime will <strong>reallocate</strong> the backing array, copy the existing elements to the new array, and append the new element.</p>\n<blockquote>\n<p>This was what I meant by &#34;slices are abstraction over arrays&#34;. Go abstracts the memory management from the developer so you don&#39;t need to think if the backing array is full, or how much of an extra capacity should I allocate every time. In C for example, you would need to use <code>calloc</code> or <code>realloc</code><sup id=\"fnref:3\"><a href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\">3</a></sup> to handle the reallocation of the memory, manually.</p>\n</blockquote>\n<p>The new capacity will be <strong>double the previous capacity</strong> until the slice reaches a certain capacity threshold. After that, the capacity will <strong>increase monotonically with different growth factors</strong>.</p>\n<p>You can see in other (older) resources that the capacity increases by 25% after 1024 items, but <a href=\"https://github.com/golang/go/commit/2dda92ff6f9f07eeb110ecbf0fc2d7a0ddd27f9d\" target=\"_blank\">in 2021 the growth formula was changed</a> to be smoother.</p>\n<p>Below is the <em>theoretical</em><sup id=\"fnref:4\"><a href=\"#fn:4\" class=\"footnote-ref\" role=\"doc-noteref\">4</a></sup> growth factors by certain capacity thresholds:</p>\n<table>\n<thead>\n<tr>\n<th>Starting Capacity</th>\n<th>Growth Factor</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>256</td>\n<td>2.0</td>\n</tr>\n<tr>\n<td>512</td>\n<td>1.63</td>\n</tr>\n<tr>\n<td>1024</td>\n<td>1.44</td>\n</tr>\n<tr>\n<td>2048</td>\n<td>1.35</td>\n</tr>\n<tr>\n<td>4096</td>\n<td>1.30</td>\n</tr>\n</tbody>\n</table>\n<p>So if we add one more item at the end of the slice <code>s2</code> we had, the <code>append</code> function will allocate a new array with a capacity of 20, copy the existing elements to the new array, and append the new element.</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s2</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">20</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p><goslice name=\"old array\" cap=\"10\" ptr=\"0x1234\" items=\"0,2,4,6,8,10,12,14,16,18\" hidelegend=\"1\" slim=\"1\" theme=\"red\" highlight-ptr=\"1\"></goslice></p>\n<p><goslice name=\"s2 []int\" cap=\"20\" ptr=\"0x2020\" items=\"0,2,4,6,8,10,12,14,16,18,20\" highlight-ptr=\"1\"></goslice></p>\n<p>Notice how <code>s2</code> now points to a <strong>different backing array</strong> with a capacity of 20. The old array at memory address <code>0x1234</code> will be <strong>garbage collected by the Go runtime</strong><sup id=\"fnref:5\"><a href=\"#fn:5\" class=\"footnote-ref\" role=\"doc-noteref\">5</a></sup> if no other slice points to it (references it).</p>\n<blockquote data-quote-character=\"sazak-explain\" class=\"quote-character\"><p> Keep in mind that the memory addresses I use in examples are just for demonstration purposes. In reality, the memory addresses are longer 32-bit or 64-bit integers and can change between runs.</p>\n</blockquote>\n<p><newslettercard></newslettercard></p>\n<h3 id=\"a-note-on-append-function\">A note on append function</h3>\n<p>In many places you will see the <code>append</code> function used with the same slice as the first argument, like <code>sl = append(sl, &#34;hello&#34;)</code>.</p>\n<p>This is because when the slice given exceeds the capacity with the given new elements and <code>append</code> needs to internally reallocate a new backing array, the new slice structure pointing to the new array will be returned from the function. The slice given in the first argument, however, will not be updated in-place.</p>\n<p>That&#39;s why if you want the update to be reflected to the slice, you need to assign the result of the <code>append</code> function to the slice, as how <code>append</code> is used for most of the time.</p>\n<p>It&#39;s good to know how using different variables for the result of the <code>append</code> function can affect the slices. Consider the following example:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">dogs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">string</span><span style=\"\">{</span><span style=\"color:#f1fa8c\">&#34;bulldog&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;poodle&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;beagle&#34;</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\"></span><span style=\"\">moreDogs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">dogs</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;husky&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"\">moreAndMoreDogs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">moreDogs</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;shiba inu&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p>Before the append, <code>dogs</code> has both length and capacity of 3, and points to the backing array with the elements <code>&#34;bulldog&#34;</code>, <code>&#34;poodle&#34;</code>, and <code>&#34;beagle&#34;</code>. As <code>dogs</code> is at full capacity, the first append call will return a new slice, pointing to a new backing array filled with the initial elements and the new element <code>&#34;husky&#34;</code>, with a capacity of 6.</p>\n<p>Now <code>moreDogs</code> points to the new backing array, and <code>dogs</code> still points to the old backing array. In the second append call, we would not expect another reallocation happening, as the <code>moreDogs</code> slice has enough capacity to hold the new element <code>&#34;shiba inu&#34;</code>. So the <code>moreAndMoreDogs</code> slice will point to the same backing array as <code>moreDogs</code>.</p>\n<h2 id=\"slicing\">Slicing</h2>\n<p>We can create a new slice from an existing slice by using the slicing expression. It&#39;s syntactically similar to what Python does with lists.</p>\n<p>When we slice another slice, the new slice will point to the same backing array, but the length and capacity will be different, <strong>depending on the range we specify</strong>. The range is inclusive for the start index and exclusive for the end index.</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s1</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">byte</span><span style=\"\">{</span><span style=\"color:#bd93f9\">16</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">64</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">80</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\"></span><span style=\"\">s2</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">[</span><span style=\"color:#bd93f9\">1</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s1: %v, len: %d, cap: %d\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">s1</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">cap</span><span style=\"\">(</span><span style=\"\">s1</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s2: %v, len: %d, cap: %d\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">cap</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">))</span><span style=\"\">\n</span></span></span></code></pre><p>The code above will output:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s1: </span><span style=\"color:#ff79c6\">[</span><span style=\"color:#bd93f9\">16</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\"> </span><span style=\"color:#bd93f9\">64</span><span style=\"\"> 80</span><span style=\"color:#ff79c6\">]</span><span style=\"\">, len: 5, cap: </span><span style=\"color:#bd93f9\">5</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">s2: </span><span style=\"color:#ff79c6\">[</span><span style=\"color:#bd93f9\">32</span><span style=\"\"> 48</span><span style=\"color:#ff79c6\">]</span><span style=\"\">, len: 2, cap: </span><span style=\"color:#bd93f9\">4</span><span style=\"\">\n</span></span></span></code></pre><p>Length of <code>s2</code> is <code>2</code>, as the range <code>[1:3]</code> includes the elements at indexes <code>1</code> and <code>2</code>. The capacity will be the capacity of <code>s1</code> minus the start index, which is <code>4</code>.</p>\n<p>If we look at the pointers of the slices, we will see that they <strong>don&#39;t</strong> point to the same memory address:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s1: %p\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s2: %p\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s2</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s1: 0x0010\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">s2: 0x0011\n</span></span></span></code></pre><p>Notice how the pointer of <code>s2</code> is one byte ahead of the pointer of <code>s1</code>. This is because the slice <code>s2</code> starts from the second element of the slice <code>s1</code>, and as each element in slice <code>s1</code> is one byte long (<code>byte</code>), the second item is one byte ahead of the first item.</p>\n<p><goslice name=\"s1 []byte\" cap=\"5\" items=\"16,32,48,64,80\" ptr=\"0x0010\" startaddress=\"0x0010\" theme=\"blue\" hidelegend=\"1\" highlight-ptr=\"1\"></goslice><br/>\n<goslice name=\"s2 []byte\" cap=\"4\" items=\"32,48\" ptr=\"0x0011\" startaddress=\"0x0011\" theme=\"purple\" hidelegend=\"1\" highlight-ptr=\"1\"></goslice></p>\n<p>Let&#39;s play a little bit on our new slice <code>s2</code>. Can you guess the outcome of the following code?</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s2</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">101</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p>Remember that <code>s2</code> points to the same backing array as <code>s1</code>, and has enough capacity (4) to hold two more elements. So the new slice <code>s2</code> will be:</p>\n<p><goslice name=\"s2 []byte\" cap=\"4\" items=\"32,48,100,101\" ptr=\"0x0011\" theme=\"purple\" hidelegend=\"1\"></goslice></p>\n<p>And, as the slice <code>s1</code> still points to the same backing array, it will look like the following in memory:</p>\n<p><goslice name=\"s1 []byte\" cap=\"5\" items=\"16,32,48,100,101\" ptr=\"0x0010\" theme=\"blue\" hidelegend=\"1\"></goslice></p>\n<p>Notice how the slice <code>s1</code> is also updated, as it points to the same backing array as <code>s2</code>.</p>\n<p>Now that <code>s2</code> is at full capacity, you know that if we append one more element to <code>s2</code>, the backing array will be reallocated, and the slice will point to a new array.</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s2</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">102</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p><goslice name=\"s2 []byte\" cap=\"8\" items=\"32,48,100,101,102\" ptr=\"0x0050\" startaddress=\"0x0050\" theme=\"purple\" highlight-ptr=\"1\"></goslice></p>\n<p><code>s2</code> now points to a new backing array in a different memory address (<code>0x0050</code>), with a capacity of <code>8</code>.</p>\n<blockquote data-quote-character=\"beaver-question-3\" class=\"quote-character\"><p> What will happen to <code>s1</code> in this case?</p>\n</blockquote>\n<p>Normally the old array would be garbage collected, but in this case, <code>s1</code> still points to it, so it will not be garbage collected.</p>\n<p><goslice name=\"s1 []byte\" cap=\"5\" items=\"16,32,48,100,101\" ptr=\"0x0010\" startaddress=\"0x0010\" theme=\"blue\"></goslice></p>\n<p>See how appending to a slice which shares the same backing array with another slice <strong>can affect both slices, until one exceeds its capacity</strong> and it has a new reallocated backing array.</p>\n<h3 id=\"specifying-the-capacity\">Specifying the capacity</h3>\n<p>Different slices using the same backing array may cause implicit problems sometimes. The new slice used in a function or in another part of the code appending new elements to the slice may cause the original slice to change its contents, which may not be the desired behavior.</p>\n<blockquote data-quote-character=\"beaver-question\" class=\"quote-character\"><p> How can I prevent this behavior then?</p>\n</blockquote>\n<p>Go allows us to specify the capacity of the new slice by using a <strong>third argument</strong> in the slicing expression. This is useful when we want to limit the capacity of the new slice, to prevent the slice to change the contents <strong>out of the specified bounds</strong> of the backing array.</p>\n<p>If we would like to create a new slice from <code>s1</code> starting from the second element and ending at the third element, with a capacity of 2, we can do it like this:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s3</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">[</span><span style=\"color:#bd93f9\">1</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">]</span><span style=\"\">\n</span></span></span></code></pre><p>This will create a new slice <code>s3</code> with a length of 2 (indexes <code>1</code> and <code>2</code>), a capacity of 2 as specified, and it will point to the second item (index <code>1</code>) of the same backing array as <code>s1</code>. Notice that the third argument is <strong>not</strong> the capacity of the new slice, but in which index the capacity should end.</p>\n<p>Now if we append a to <code>s3</code>, as <code>s3</code> is at capacity (<code>len(s3)</code> == <code>cap(s3)</code> == <code>2</code>) it will cause a reallocation of the used parts of the backing array, but it will not affect the contents of <code>s1</code>.</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s1</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">byte</span><span style=\"\">{</span><span style=\"color:#bd93f9\">16</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">64</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">80</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\"></span><span style=\"\">s3</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">[</span><span style=\"color:#bd93f9\">1</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"\">s3</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s3</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">200</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">201</span><span style=\"\">)</span><span style=\"\">\n</span></span></span></code></pre><p><goslice name=\"s3 []byte\" cap=\"8\" items=\"32,48,200,201\" ptr=\"0x0060\" startaddress=\"0x0060\" theme=\"yellow\" hidelegend=\"1\" highlight-ptr=\"1\"></goslice><br/>\n<goslice name=\"s1 []byte\" cap=\"5\" items=\"16,32,48,64,80\" ptr=\"0x0010\" startaddress=\"0x0010\" theme=\"blue\"></goslice></p>\n<p>Notice how the ptr of <code>s3</code> is different as it now points to a new backing array with length of 4 (2 old elements copied and two newly appended), and capacity of 4 (twice as the old capacity). The contents of <code>s1</code> after the index <code>2</code> are not affected by the append operation on <code>s3</code>.</p>\n<p>The whole code snippet is below:</p>\n<pre data-filename=\"go.dev/play/p/DrKX2QE24QP\" data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"\">s1</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">byte</span><span style=\"\">{</span><span style=\"color:#bd93f9\">16</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">64</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">80</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\"></span><span style=\"\">s2</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">[</span><span style=\"color:#bd93f9\">1</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\"></span><span style=\"\">s2</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">101</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\"></span><span style=\"\">s2</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">102</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s1: %v, len: %d, cap: %d\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">s1</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">cap</span><span style=\"\">(</span><span style=\"\">s1</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s2: %v, len: %d, cap: %d\\n\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s2</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">cap</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\"></span><span style=\"\">s1</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#8be9fd\">byte</span><span style=\"\">{</span><span style=\"color:#bd93f9\">16</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">64</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">80</span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\"></span><span style=\"\">s3</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">[</span><span style=\"color:#bd93f9\">1</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">:</span><span style=\"color:#bd93f9\">3</span><span style=\"\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s3 initially: %v, len: %d, cap: %d\\n\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s3</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">cap</span><span style=\"\">(</span><span style=\"\">s3</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\"></span><span style=\"\">s3</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">s3</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">200</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">201</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s1: %v, len: %d, cap: %d\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s1</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">s1</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">cap</span><span style=\"\">(</span><span style=\"\">s1</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\"></span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;s3: %v, len: %d, cap: %d\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">s3</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">s2</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">cap</span><span style=\"\">(</span><span style=\"\">s3</span><span style=\"\">))</span><span style=\"\">\n</span></span></span></code></pre><pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">s1: </span><span style=\"color:#ff79c6\">[</span><span style=\"color:#bd93f9\">16</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\"> 101</span><span style=\"color:#ff79c6\">]</span><span style=\"\">, len: 5, cap: </span><span style=\"color:#bd93f9\">5</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">s2: </span><span style=\"color:#ff79c6\">[</span><span style=\"color:#bd93f9\">32</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\"> </span><span style=\"color:#bd93f9\">101</span><span style=\"\"> 102</span><span style=\"color:#ff79c6\">]</span><span style=\"\">, len: 5, cap: </span><span style=\"color:#bd93f9\">8</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">s3 initially: </span><span style=\"color:#ff79c6\">[</span><span style=\"color:#bd93f9\">32</span><span style=\"\"> 48</span><span style=\"color:#ff79c6\">]</span><span style=\"\">, len: 5, cap: </span><span style=\"color:#bd93f9\">2</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">6</span><span style=\"\"><span style=\"\">s1: </span><span style=\"color:#ff79c6\">[</span><span style=\"color:#bd93f9\">16</span><span style=\"\"> </span><span style=\"color:#bd93f9\">32</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\"> </span><span style=\"color:#bd93f9\">64</span><span style=\"\"> 80</span><span style=\"color:#ff79c6\">]</span><span style=\"\">, len: 5, cap: </span><span style=\"color:#bd93f9\">5</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">7</span><span style=\"\"><span style=\"\">s3: </span><span style=\"color:#ff79c6\">[</span><span style=\"color:#bd93f9\">32</span><span style=\"\"> </span><span style=\"color:#bd93f9\">48</span><span style=\"\"> </span><span style=\"color:#bd93f9\">200</span><span style=\"\"> 201</span><span style=\"color:#ff79c6\">]</span><span style=\"\">, len: 5, cap: </span><span style=\"color:#bd93f9\">8</span><span style=\"\">\n</span></span></span></code></pre><blockquote>\n<p>Specifying the slice capacity is an option we can use to limit the new slice&#39;s capacity and actions on the items of backing array, to prevent unexpected changes in the original slice.</p>\n</blockquote>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>Slices are a powerful abstraction in Go, allowing us to work with arrays in a more flexible way. Understanding how slices work internally helps us write more efficient and less error-prone code. I hope this article helped you gain insight on how slices work under the hood, and when to pay attention to implementation details to prevent unexpected behavior.</p>\n<p>There will be more of these visual guides to Go internals in the future, and there <em>may</em> be a part two to this article.</p>\n<p>If you have any questions or feedback, feel free to reach out to me on <a href=\"https://twitter.com/oznszk\" target=\"_blank\">Twitter</a>. Until next time, stay tuned.</p>\n<h2 id=\"exercises\">Exercises</h2>\n<gocodequestion difficulty=\"easy\" playlink=\"https://go.dev/play/p/5mF1pW6SqDo\" parsetextfrom=\"questions/visual-go-slices/01.md\" parsedcontent=\"&lt;p&gt;What is the length and capacity of slice &lt;code&gt;s1&lt;/code&gt; after the operations below?&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;make&lt;/span&gt;&lt;span style=&#34;&#34;&gt;([]&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;8&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;[]&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;23&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;0x5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;23&lt;/span&gt;&lt;span style=&#34;&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;\">\n    Length will be 10 as there will be 10 items in the slice at the end. The capacity will be doubled after we add the 8th element, so it will be 16.\n    <goslice name=\"s1 []int\" cap=\"16\" items=\"1,3,5,7,9,11,100,23,5,-23\" hidelegend=\"1\" slim=\"1\" theme=\"purple\"></goslice>\n</gocodequestion>\n<gocodequestion difficulty=\"easy\" playlink=\"https://go.dev/play/p/O76cT6PnNPx\" parsetextfrom=\"questions/visual-go-slices/03.md\" parsedcontent=\"&lt;p&gt;What are the contents of the slice &lt;code&gt;funcSl&lt;/code&gt; below?&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;funcSl&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;make&lt;/span&gt;&lt;span style=&#34;&#34;&gt;([]&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;context&lt;/span&gt;&lt;span style=&#34;&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;&#34;&gt;Context&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;error&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;10&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;\">\n    The make built-in function allocates the backing array with a length of 10, which is also the capacity of the slice. The length of the slice is 5, and the backing array is filled with the zero values of the element type.<br/><br/>As the zero value of the function type is nil, no matter the function signature, the slice will be filled with 5 nil values.\n    <goslice name=\"funcSl\" cap=\"10\" items=\"nil,nil,nil,nil,nil\" hidelegend=\"1\" slim=\"1\" theme=\"red\"></goslice>\n</gocodequestion>\n<gocodequestion difficulty=\"medium\" playlink=\"https://go.dev/play/p/MrPYo1CRJ2w\" parsetextfrom=\"questions/visual-go-slices/02.md\" parsedcontent=\"&lt;p&gt;What are the lengths and capacities of slices &lt;code&gt;s1&lt;/code&gt;, &lt;code&gt;s2&lt;/code&gt;, and &lt;code&gt;s3&lt;/code&gt; after the operations below?&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;make&lt;/span&gt;&lt;span style=&#34;&#34;&gt;([]&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;string&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;B&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s2&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;C&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s3&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;D&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;\">\n    After the first two index assignments, s1 will have &#34;A&#34; and &#34;B&#34; as first two items.<br/><br/>When we append &#34;C&#34; to s1, the append function will not reallocate the backing array as s1 is not at capacity, and append will return a slice pointing to the same backing array with a length of 3 and capacity of 5, which is assigned to s2.<br/><br/>The last append to s2 will not reallocate as well, as the capacity is enough to hold the new element, and return a slice with a length of 4 and capacity of 5. All slices will point to the same backing array and have the same capacities, but with different lengths.\n    <goslice name=\"s1 []string\" cap=\"5\" ptr=\"0x0015\" startaddress=\"0x0015\" items=\"A,B\" hidelegend=\"1\" slim=\"1\" theme=\"red\"></goslice>\n    <goslice name=\"s2 []string\" cap=\"5\" ptr=\"0x0015\" startaddress=\"0x0015\" items=\"A,B,C\" hidelegend=\"1\" slim=\"1\" theme=\"yellow\"></goslice>\n    <goslice name=\"s3 []string\" cap=\"5\" ptr=\"0x0015\" startaddress=\"0x0015\" items=\"A,B,C,D\" hidelegend=\"1\" slim=\"1\" theme=\"purple\"></goslice>\n</gocodequestion>\n<gocodequestion difficulty=\"hard\" playlink=\"https://go.dev/play/p/mvOgJqDwBrf\" parsetextfrom=\"questions/visual-go-slices/04.md\" parsedcontent=\"&lt;p&gt;What are the contents, length and capacities of slices &lt;code&gt;s1&lt;/code&gt;, &lt;code&gt;s2&lt;/code&gt;, and &lt;code&gt;s3&lt;/code&gt; after the operations below?&lt;/p&gt;\n&lt;pre data-language=&#34;go&#34; tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;&#34;&gt;&lt;code&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;[]&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;byte&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Hello world!&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s2&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;[:&lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s2&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s2&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;[]&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;byte&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;gophers&amp;#34;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s3&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;s1&lt;/span&gt;&lt;span style=&#34;&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#bd93f9&#34;&gt;11&lt;/span&gt;&lt;span style=&#34;&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;&#34;&gt;&lt;span style=&#34;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s3&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;&#34;&gt;s3&lt;/span&gt;&lt;span style=&#34;&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;byte&lt;/span&gt;&lt;span style=&#34;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;?&amp;#39;&lt;/span&gt;&lt;span style=&#34;&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;&#34;&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;\">\n    At first s1 is a byte slice with a length and capacity of 12, and with items &#39;H&#39;, &#39;e&#39;, &#39;l&#39;, &#39;l&#39;, &#39;o&#39;, etc. After the first slicing operation, s2 will be a byte slice pointing to the same memory location as s1, with length 6 and capacity 12.<br/><br/>Appending the items of []byte(&#34;gophers&#34;) means appending 7 bytes to s2, which is out of the capacity of s2. So the first append will allocate a new backing array, copy the items of s2 to the new array, and append the new items. The new slice s2 will point to the new backing array with a length of 13 and a capacity of 24<br/><br/>After the second slicing, s3 will point to the 7th item of s1, with a length of 5 and a capacity of 6. The last append will not reallocate the backing array, as s3 has enough capacity to hold the new item, and the new slice will have a length of 6 and a capacity of 6.<br/><br/>When we call append the second time on s3 and append one byte to it, s3 will be at full capacity and have length and capacity of 6. As this call did not reallocate and both s1 and s3 point to the same backing array, the last item of s1 will be updated as well.\n    <goslice name=\"s []byte\" cap=\"12\" ptr=\"0x1000\" startaddress=\"0x1000\" items=\"H,e,l,l,o, ,w,o,r,l,d,?\" theme=\"green\"></goslice>\n    <goslice name=\"s2 []byte\" cap=\"24\" ptr=\"0x1230\" startaddress=\"0x1230\" items=\"H,e,l,l,o, ,g,o,p,h,e,r,s\" theme=\"blue\"></goslice>\n    <goslice name=\"s3 []byte\" cap=\"6\" ptr=\"0x1006\" startaddress=\"0x1006\" items=\"w,o,r,l,d,?\" theme=\"purple\"></goslice>\n</gocodequestion>\n<h2 id=\"references\">References</h2>\n<ul>\n<li><a href=\"https://github.com/golang/go\" target=\"_blank\">Go compiler source code</a></li>\n<li><a href=\"https://go.dev/doc/effective_go\" target=\"_blank\">Effective Go</a></li>\n<li><a href=\"https://100go.co\" target=\"_blank\">100 Go Mistakes and How to Avoid Them</a></li>\n<li><a href=\"https://go.dev/blog/slices-intro\" target=\"_blank\">Go Slices: usage and internals</a></li>\n</ul>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr/>\n<ol>\n<li id=\"fn:1\" data-index=\"1\">\n<p>Zero value is the default value of an uninitialized type in Go. For example, the zero value of a <code>bool</code> is <code>false</code>, integer types are <code>0</code>, and slices, functions, maps, etc. are <code>nil</code>. <a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:2\" data-index=\"2\">\n<p>The <code>range</code> keyword is used to iterate over the indexes and (optionally) the values of an array or slice. It returns the index and the value of each element. If the result is decomposed into one variable such as <code>i := range slice</code>, it will only return the index. If it is decomposed into two variables such as <code>i, v := range slice</code>, it will return both the index and the value. Similarly, if you only need the value, you can use <code>_</code> to discard the index, such as <code>_, v := range slice</code>. The <code>range</code> iteration behaves differently on <code>map</code>s and <code>channel</code>s. <a href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:3\" data-index=\"3\">\n<p><a href=\"https://linux.die.net/man/3/realloc\" target=\"_blank\">linux.die.net/man/3/realloc</a> <a href=\"#fnref:3\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:4\" data-index=\"4\">\n<p>The growth factors are not <strong>constant</strong>, in practice. To see the actual calculation of the &#34;smooth&#34; growth factors, you can check the <code>nextslicecap</code> function in <a href=\"https://github.com/golang/go/blob/c2c4a32f9e57ac9f7102deeba8273bcd2b205d3c/src/runtime/slice.go#L282\" target=\"_blank\">Go runtime source code</a>. <a href=\"#fnref:4\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:5\" data-index=\"5\">\n<p>For more info about the garbage collector, see <a href=\"https://tip.golang.org/doc/gc-guide\" target=\"_blank\">tip.golang.org/doc/gc-guide</a> <a href=\"#fnref:5\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>\n",
            "url": "https://sazak.io/articles/visual-guide-to-slices-in-go-2024-03-25",
            "title": "Visual Guide to Slices in Go",
            "summary": "This visual guide shows how slices work under the hood in Go, covers slice creation, manipulation using make and append, how capacity grows, and slicing syntax for creating new slices from existing ones.",
            "image": "https://sazak.io/assets/articles/visual-guide-to-slices-in-go-2024-03-25.jpeg",
            "date_modified": "2024-03-25T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/articles/how-i-built-my-own-go-package-index---gosazakio-2024-03-10",
            "content_html": "<p>One of the things I like about Go is that when you want to use someone else&#39;s code in your project, you can just import it by its GitHub repo URL.</p>\n<p>Literally, you can just import the package by writing:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#ff79c6\">import</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;github.com/google/go-cmp/cmp&#34;</span><span style=\"\">\n</span></span></span></code></pre><p>And that&#39;s it. Although these URLs don&#39;t have to be GitHub URLs. Sometimes you see import paths like <code>go.uber.org/atomic</code>, or <code>golang.org/x/crypto/ssh</code>.</p>\n<p>These are also valid import paths and they are called <strong>&#34;vanity import paths&#34;</strong>. They are called &#34;vanity&#34; because they are custom domain names, which redirect to the actual repository.</p>\n<h2 id=\"how-does-it-work\">How does it work?</h2>\n<p>The work behind the scenes is pretty simple: When you run <code>go get</code>, or <code>go install</code>, Go tooling sends an HTTP request to this URL to get the package info, then downloads the source code under the <code>vendor</code> directory. The package info is provided in <strong>meta tags</strong> in the HTML response, which are:</p>\n<p><strong>go-import</strong>: Where to find the repository. It has three parts: the import path, the VCS type (git, hg, etc.), and the repository URL.</p>\n<p><img src=\"/assets/articles/go-sazak-io/go-import.png\" alt=\"\" loading=\"lazy\"/></p>\n<p><strong>go-source</strong>: Optional information for <a href=\"https://pkg.go.dev\" target=\"_blank\">pkg.go.dev</a> to link to the source code.</p>\n<p><img src=\"/assets/articles/go-sazak-io/go-source.png\" alt=\"\" loading=\"lazy\"/></p>\n<p>The idea is, by simply returning these meta tags in the HTML response, you can make your own Go package index.</p>\n<h2 id=\"but-why\">But why?</h2>\n<p>Why not? I like building stuff and putting them in public repos. I also use my own packages/tools later in other projects. So, I thought it would be cool to step it up a bit and have my own domain for my Go packages.</p>\n<p>It&#39;s better to use this:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#ff79c6\">import</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;go.sazak.io/my-package&#34;</span><span style=\"\">\n</span></span></span></code></pre><p>Instead of this:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#ff79c6\">import</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;github.com/ozansz/my-package&#34;</span><span style=\"\">\n</span></span></span></code></pre><p>That&#39;s how <a href=\"https://go.sazak.io\" target=\"_blank\">go.sazak.io</a> was born. It&#39;s a simple Go package index for my own public Go packages. It&#39;s basically a static site built by using a JSON file that contains the package info, which is also generated by a simple Go tool.</p>\n<h2 id=\"designing-the-system\">Designing the system</h2>\n<p>When you think of designing an index which lists a number of packages, which link to their respective GitHub repositories, you might think of using a database, a backend server, and a frontend client.</p>\n<p>We tend to overcomplicate things as developers, but in my opinion it&#39;s the best solution to keep things as simple as possible while preserving the functionality and developer experience.</p>\n<blockquote data-quote-character=\"gopher-info\" class=\"quote-character\"><p> &#34;Simple is better than complex.&#34; - Zen of Python</p>\n</blockquote>\n<p>The whole systems consists of two parts: a Go tool called <code>sync-github-repos</code> that collects and compiles the data, and the static site that uses the JSON file as the data source to build a static site.</p>\n<p><img src=\"/assets/articles/go-sazak-io/overall.png\" alt=\"\" loading=\"lazy\"/></p>\n<h3 id=\"the-backend\">The Backend</h3>\n<p>The tool uses GitHub API to list my public repositories, then filters the ones that have a <code>go.mod</code> file which content starts with <code>module go.sazak.io/</code>. The data is then stored inside a <code>Repo</code> Go struct to later be marshaled into a JSON file:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">Repo</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">Owner</span><span style=\"\">        </span><span style=\"color:#8be9fd\">string</span><span style=\"\">            </span><span style=\"color:#f1fa8c\">`json:&#34;owner&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">Name</span><span style=\"\">         </span><span style=\"color:#8be9fd\">string</span><span style=\"\">            </span><span style=\"color:#f1fa8c\">`json:&#34;name&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">Stars</span><span style=\"\">        </span><span style=\"color:#8be9fd\">uint</span><span style=\"\">              </span><span style=\"color:#f1fa8c\">`json:&#34;stars&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">Description</span><span style=\"\">  </span><span style=\"color:#8be9fd\">string</span><span style=\"\">            </span><span style=\"color:#f1fa8c\">`json:&#34;desc&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">GoPackage</span><span style=\"\">    </span><span style=\"color:#8be9fd\">string</span><span style=\"\">            </span><span style=\"color:#f1fa8c\">`json:&#34;go_package&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">LatestTag</span><span style=\"\">    </span><span style=\"color:#8be9fd\">string</span><span style=\"\">            </span><span style=\"color:#f1fa8c\">`json:&#34;latest_tag&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">AlphaRelease</span><span style=\"\"> </span><span style=\"color:#8be9fd\">bool</span><span style=\"\">              </span><span style=\"color:#f1fa8c\">`json:&#34;alpha_release&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">HasCLIApp</span><span style=\"\">    </span><span style=\"color:#8be9fd\">bool</span><span style=\"\">              </span><span style=\"color:#f1fa8c\">`json:&#34;has_cli_app&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">Packages</span><span style=\"\">     </span><span style=\"color:#8be9fd;font-style:italic\">map</span><span style=\"\">[</span><span style=\"color:#8be9fd\">string</span><span style=\"\">]</span><span style=\"color:#8be9fd\">string</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">`json:&#34;packages&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">\t</span><span style=\"\">MasterBranch</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">            </span><span style=\"color:#f1fa8c\">`json:&#34;master_branch&#34;`</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>Then it checks if there are any public packages (containers) of the repository, are there any releases/tags, and if the latest tag is a pre-release. It also checks the name of the default branch, which is usually <code>main</code> or <code>master</code>.</p>\n<p>The <code>HasCLIApp</code> field is a boolean that tells if the repository includes a CLI app in the <code>cmd</code> directory. This field is set if the repo has a <code>cli</code> tag.</p>\n<p>Also the <code>AlphaRelease</code> field is a boolean that tells if the latest tag is a pre-release or if the tag is below version <code>v1.0.0</code>.</p>\n<p>The JSON file is then used as the data source for the static site. The site is built with Next.js<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup>, Shadcn UI<sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup> and deployed to Vercel.</p>\n<h3 id=\"the-ui\">The UI</h3>\n<p>As I explained before, the website only needs to serve two meta tags in the HTML response. For a basic requirement like this I could just use plain HTML, but I thought it would be better to have a clean and informative UI for the human visitors.</p>\n<p>That&#39;s why I decided to use Shadcn UI and design a one-page package listing site. I used the <code>Card</code> component to display the package info for all packages. The basic information is same for all packages, for example the package name, latest tag badge, instructions to clone the repository, etc.</p>\n<p><img src=\"/assets/articles/go-sazak-io/card-1.png\" alt=\"\" loading=\"lazy\"/></p>\n<p>Cards also contain different sections, based on what package provides. If it&#39;s a CLI app, it shows the instructions to install the app. If it has packages (containers), it also shows the instructions to pull the containers using <code>docker pull</code>.</p>\n<p><img src=\"/assets/articles/go-sazak-io/card-2.png\" alt=\"\" loading=\"lazy\"/></p>\n<p>After putting it all together, the site looks like this:</p>\n<p><img src=\"/assets/articles/go-sazak-io/website.png\" alt=\"\" loading=\"lazy\"/></p>\n<p>Which, I think, is pretty cool for a simple Go package index, and also for a backend/platform engineer like me to build.</p>\n<h3 id=\"the-pipeline\">The Pipeline</h3>\n<p>To make it easier to deploy the website with the synced data, I created a <del>GitHub Actions workflow</del> pre-commit hook that runs the <code>sync-github-repos</code> tool to generate the JSON file and put it inside the UI project:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#ff79c6\">#!/bin/sh\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#ff79c6\"></span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">set</span><span style=\"\"> -eo pipefail\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">go run cmd/sync-github-repos/main.go --username ozansz --hostname go.sazak.io --out ui/src/repos.json --force-authenticated\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"color:#ff79c6\">[</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">$?</span><span style=\"\"> -ne </span><span style=\"color:#bd93f9\">0</span><span style=\"\"> </span><span style=\"color:#ff79c6\">]</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"color:#ff79c6\">then</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#8be9fd;font-style:italic\">echo</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;Pre-commit hook failed (content generation script)&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#8be9fd;font-style:italic\">exit</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\"></span><span style=\"color:#ff79c6\">fi</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">git update-index --add ui/src/repos.json\n</span></span></span></code></pre><p>After I push the changes, the Vercel deployment pipeline is triggered and the site is updated with the new data.</p>\n<p><img src=\"/assets/articles/go-sazak-io/deploy.png\" alt=\"\" loading=\"lazy\"/></p>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>It&#39;s pretty simple -and cool- to have your own Go package index. It&#39;s a good way to keep track of your own packages publicly.</p>\n<p>If you liked the idea, you can also build your own package index. My implementation for <a href=\"https://go.sazak.io\" target=\"_blank\">go.sazak.io</a> is open source and available on <a href=\"https://github.com/ozansz/go.sazak.io\" target=\"_blank\">GitHub</a>. I tried to make it as simple as possible to use and extend.</p>\n<p>Feel free to fork it and build your own package index!</p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr/>\n<ol>\n<li id=\"fn:1\" data-index=\"1\">\n<p><a href=\"https://nextjs.org/\">https://nextjs.org/</a> <a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:2\" data-index=\"2\">\n<p><a href=\"https://ui.shadcn.com/\">https://ui.shadcn.com/</a> <a href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>\n",
            "url": "https://sazak.io/articles/how-i-built-my-own-go-package-index---gosazakio-2024-03-10",
            "title": "How I built my own Go package index - go.sazak.io",
            "summary": "I built my own Go package index with a static site using Go, Next.js and Shadcn UI. Here's how I did it.",
            "image": "https://sazak.io/assets/articles/how-i-built-my-own-go-package-index---gosazakio-2024-03-10.jpeg",
            "date_modified": "2024-03-10T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/talks/an-applied-introduction-to-ebpf-with-go-2024-02-17",
            "content_html": "<p>I had the opportunity to speak at Go Konf Istanbul about developing eBPF programs with Go, and how we use eBPF at Edge Delta. Go Konf was organized by Istanbul Gophers, a local Go community in Istanbul, and was the first in-person Go conference in Istanbul, as I recall. There were many great talks (I especially liked <a href=\"https://twitter.com/fatih\" target=\"_blank\">Fatih</a>&#39;s talk on the new expeimental function iterators).</p>\n",
            "url": "https://sazak.io/talks/an-applied-introduction-to-ebpf-with-go-2024-02-17",
            "title": "An Applied Introduction to eBPF with Go",
            "summary": "I had the opportunity to speak at Go Konf Istanbul about developing eBPF programs with Go, and how we use eBPF at Edge Delta. Go Konf was the first in-person Go conference in Istanbul, as I recall, and there were many great talks. Happy to be a part of it.",
            "image": "https://sazak.io/assets/talks/an-applied-introduction-to-ebpf-with-go-2024-02-17.jpeg",
            "date_modified": "2024-02-17T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/reading-groups/street-coder---sedat-kapanoglu-2023-11-07",
            "content_html": "<p>Street Coder is the first book we read in our tech book reading club, Reading Stacks. We meet every two weeks to discuss a chapter or two from a tech book. We started with &#39;Street Coder&#39; by Sedat Kapanoglu. The book is written for self-taught developers, talking about foundational concepts and best practices in software development.</p>\n<p>Some of the chapters were a little much opinionated, but it was a good read overall. I wouldn&#39;t say I learned something new, but it was a good refresher on some of the topics, and also I felt challenged to think about some of the topics from a different perspective.</p>\n<h2 id=\"organizers\">Organizers</h2>\n<p>We are a group of friends from METU, Turkey.</p>\n<ul>\n<li><a href=\"https://twitter.com/Keleesssss\" target=\"_blank\">Alperen Keleş</a></li>\n<li><a href=\"https://twitter.com/ozn_akn\" target=\"_blank\">Ozan Akın</a></li>\n<li><a href=\"https://twitter.com/oznszk\" target=\"_blank\">Ozan Sazak (me 👋)</a></li>\n<li><a href=\"https://twitter.com/yigit_v4rli\" target=\"_blank\">Yiğit Varlı</a></li>\n</ul>\n",
            "url": "https://sazak.io/reading-groups/street-coder---sedat-kapanoglu-2023-11-07",
            "title": "Street Coder - Sedat Kapanoglu",
            "summary": "Reading Stacks is a tech book reading club we started with a few friends from METU. We meet every two weeks to discuss a chapter or two from a tech book. We started with 'Street Coder' by Sedat Kapanoglu.",
            "date_modified": "2023-11-07T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/articles/fantastic-side-projects-and-where-to-find-them-2023-09-03",
            "content_html": "<p>So you are a newbie developer looking for a project idea to apply what you&#39;ve learned in that Udemy course, or maybe an experienced engineer searching for the next side project to work on for fun. Either way, you need a creative idea to bring to life.</p>\n<p>It&#39;s a fun way to apply what you have learned in the courses/books and an excellent skill to craft the tool you just need to automate that boring stuff you need to do every day.</p>\n<p>Here, I will list a few sources/techniques I used to find cool project ideas while learning programming and now to craft useful tools for my needs. <strong>This blog post is a little bit opinionated.</strong> Everyone has a unique learning curve, so if you find my suggestions harder or easier than expected, it&#39;s okay to modify them to fit your level.</p>\n<p><img src=\"/assets/articles/project-complexity-by-time-graph.png\" alt=\"\" loading=\"lazy\"/></p>\n<h2 id=\"you-have-just-started-learning-programming\">you have just started learning programming...</h2>\n<p>...and looking for project ideas. You probably know Python or JavaScript a little bit, or maybe C/Go, and want to dive into interesting real-life stuff.</p>\n<p>In this stage, you should <strong>not</strong> dive right into big and complex projects. I know it&#39;s exciting, but hear my reasons:</p>\n<ol>\n<li><strong>You probably don&#39;t have the technical background required to build a complex system.</strong> Whether it&#39;s creating a browser, a search engine, a social media app, …. These projects seem simple from the outside. <em>&#34;I mean, you just enter a search text, and it lists some websites&#34;</em>, yes, but in the background, there are too many moving parts and some pretty complex algorithms for a beginner. For a browser, you need to write a JavaScript parser; for a search engine, you at least need to understand graphs, and so on.</li>\n<li><strong>You may not have the ability to read other people&#39;s code.</strong> Building complex stuff requires the skill (yes, it&#39;s kind of a skill) to read long lines of production code to see how other engineers solved similar problems. Also, you can&#39;t always find blog posts/videos/docs explaining <em>&#34;how to do X&#34;</em> after a certain level of problem complexity.</li>\n</ol>\n<p><strong>However</strong>, the most beneficial thing you can do is code simple yet not tedious stuff using the programming topics you learned to jump to advanced levels where you can work on complex projects as fast as possible.</p>\n<p>I suggest <strong>coding simple versions</strong> of those complex programs, such as <strong>creating little terminal-based games</strong>. You don&#39;t need to learn GUI, a self-made hangman game is still fun after all. Also, while building one, you will need to use most of the topics you&#39;ve learned/are learning: fundamental data types, variables, control flow (conditionals, loops), terminal input/output, etc…</p>\n<p>Another one may be <strong>a simple chatbot in the terminal</strong>. It gives you a list of prompt options, you select one, and it prints a defined answer for the fixed prompt. It&#39;s like a super simple version of ChatGPT - you don&#39;t need to design and code all the frontend, backend, and ML stuff.</p>\n<h2 id=\"you-had-some-time-with-a-programming-language-and-can-write-basic-programs\">you had some time with a programming language and can write basic programs</h2>\n<p>Perfect! Now you are ready to step up your game a little bit and start learning and applying CS fundamentals in your programs to reach a higher level of complexity:</p>\n<ul>\n<li><strong>Basic data structures</strong>. Array, linked list, tree, hash map, and stack/queue data structures are in this category.</li>\n<li><strong>Basic algorithms</strong>.</li>\n<li><strong>File operations</strong>. You won&#39;t only interact with the user via the terminal input all the time. Sometimes, you need other communication mediums, and one of the most fundamental ones is <strong>through using a simple file</strong>.</li>\n</ul>\n<p>In this stage, you can add more functionality to the programs you have created until now, adding <strong>dynamism</strong> by implementing:</p>\n<ul>\n<li>Updating the program data during runtime</li>\n<li>Not-strictly-defined user interactions</li>\n</ul>\n<blockquote data-quote-character=\"gopher-info\" class=\"quote-character\"><p> The idea is forcing yourself to use a new data structure/algorithm in every project you create.</p>\n</blockquote>\n<p>Let&#39;s say you have a program that gives you the information of students when you enter the name of one. You can enhance this program to run in a loop that takes the student name, gives the info, <strong>then asks the user if they want to update</strong> the information. To do this, you will need to use a data structure (<a href=\"https://en.wikipedia.org/wiki/Linked_list\" target=\"_blank\">linked list</a>, for example) instead of hardcoded data. Then, you will need to use a <a href=\"https://en.wikipedia.org/wiki/Search_algorithm\" target=\"_blank\">search algorithm</a> to find specific students given the name.</p>\n<p>Adding more functionality pushes you to utilize new stuff in your code, which is an excellent way to learn and practice new concepts in programming.</p>\n<!-- \n```d2\ndirection: right\n\nCode -&gt; Add more functionality -&gt; Learn new stuff -&gt; Code: {\n style.animated: true\n}\n``` -->\n<h2 id=\"you-are-fluent-in-a-programming-language-and-know-basic-cs-theory\">you are fluent in a programming language and know basic CS theory</h2>\n<p>This is the time you need to start learning more advanced stuff. Such as:</p>\n<ul>\n<li><strong>Storing and retrieving application data.</strong> How/when to use JSON/CSV files, SQL databases, caches, message queues, data serialization algorithms, etc.</li>\n<li><strong>Interprocess communication.</strong> This is where the distributed systems practically begin. As the complexity increases, you will need your programs to talk to each other.</li>\n<li><strong>Beyond basic data structures and algorithms.</strong> You can put graphs, tries, B+ trees, and bloom filters in this category. These data structures are used inside browsers, databases, search engines, and many more complex systems.</li>\n</ul>\n<p>In this stage, you can try to design and implement <strong>your own version of existing stuff</strong> you use, such as creating your own programming language and writing a compiler for it, trying to write your own database engine with indexes, basic queries, and maybe aggregations.</p>\n<p><strong>You don&#39;t have to go with a fully functional clone</strong>; for example, creating a programming language with just integer types as the native type is a good exercise, and it&#39;s still challenging!</p>\n<p>Here are some practical resources and project ideas:</p>\n<ul>\n<li><strong>Try to read the Python source code</strong>. The official implementation<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> is done in C, and it&#39;s a good exercise to go over and try to understand how the native data types (<code>int</code>, <code>list</code>, <code>dict</code>, etc.) are implemented, how did they handle memory management, and so on.</li>\n<li>If you are fluent in Python and can code at least a little bit of C, try to write a <strong>Python extension</strong><sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></li>\n<li><strong>Try to design and implement your own programming language</strong>. This is a fun project because until now, you were on the consumer side of the languages (if you did not contribute to a programming language), <em>and now you will be on the creator side!</em> Interpreters and compilers are complex computer science topics, but you don&#39;t need to know them in detail to implement a simple language processor.</li>\n<li><strong>Create a blog engine</strong>. You can develop your own static site generator<sup id=\"fnref:3\"><a href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\">3</a></sup> and start blogging using your own blog engine. Checking some of the popular static site generators, such as Hugo<sup id=\"fnref:4\"><a href=\"#fn:4\" class=\"footnote-ref\" role=\"doc-noteref\">4</a></sup> and Zola<sup id=\"fnref:5\"><a href=\"#fn:5\" class=\"footnote-ref\" role=\"doc-noteref\">5</a></sup>, can help determine which features to implement in your engine.</li>\n</ul>\n<p>Some good resources worth reading/checking for <strong>compiler/interpreter design</strong>:</p>\n<ul>\n<li><a href=\"https://interpreterbook.com/\" target=\"_blank\">Writing An Interpreter In Go</a> - Book by Thorsten Ball, going through the steps of writing an interpreter from scratch for a toy programming language</li>\n<li><a href=\"https://compilerbook.com/\" target=\"_blank\">Writing A Compiler In Go</a> - Book by Thorsten Ball, sequel to Writing An Interpreter In Go</li>\n<li><a href=\"https://craftinginterpreters.com/\" target=\"_blank\">Crafting Interpreters</a> - Book by Robert Nystrom, a good read on interpreter internals</li>\n<li><strong>Compilers: Principles, Techniques, and Tools</strong> - The Dragon Book. Maybe the most popular compiler book among the CS students :)</li>\n<li><a href=\"https://github.com/DoctorWkt/acwj\" target=\"_blank\">A Compiler Writing Journey</a> - GitHub repo of a self-compiling compiler project. There are implementation notes for all parts, it&#39;s worth checking out.</li>\n</ul>\n<h2 id=\"you-are-capable-of-designing-and-implementing-complex-stuff\"><del>you are capable of designing and implementing complex stuff</del></h2>\n<p>This blog post became longer than I expected, and it&#39;s been a while since I started writing, so I will write another one just for this subtopic 🤷‍♂️</p>\n<h2 id=\"thats-all\">that&#39;s all!</h2>\n<p>I hope you found this content useful. I will add sequels to this post, writing about my side projects or other resources to find fun side project ideas in the future.</p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr/>\n<ol>\n<li id=\"fn:1\" data-index=\"1\">\n<p><a href=\"https://github.com/python/cpython\" target=\"_blank\">https://github.com/python/cpython</a> <a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:2\" data-index=\"2\">\n<p><a href=\"https://realpython.com/build-python-c-extension-module/\" target=\"_blank\">https://realpython.com/build-python-c-extension-module/</a> <a href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:3\" data-index=\"3\">\n<p><a href=\"https://www.cloudflare.com/learning/performance/static-site-generator/\" target=\"_blank\">https://www.cloudflare.com/learning/performance/static-site-generator/</a> <a href=\"#fnref:3\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:4\" data-index=\"4\">\n<p><a href=\"https://github.com/gohugoio/hugo\" target=\"_blank\">https://github.com/gohugoio/hugo</a> <a href=\"#fnref:4\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:5\" data-index=\"5\">\n<p><a href=\"https://www.getzola.org/\" target=\"_blank\">https://www.getzola.org/</a> <a href=\"#fnref:5\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>\n",
            "url": "https://sazak.io/articles/fantastic-side-projects-and-where-to-find-them-2023-09-03",
            "title": "Fantastic Side Projects and Where to Find Them",
            "summary": "Here are the advices you need to check if you're searching for a cool side project idea.",
            "image": "https://sazak.io/assets/articles/fantastic-side-projects-and-where-to-find-them-2023-09-03.jpeg",
            "date_modified": "2023-09-03T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/articles/cloud-native-patterns-illustrated-fan-in-and-fan-out-2022-10-30",
            "content_html": "<p>I&#39;ve started reading technical books after my graduation from CS to broaden my knowledge on many topics, such as system design, low-level CS, cloud native, etc. Nowadays, I&#39;m reading <a href=\"https://www.oreilly.com/library/view/cloud-native-go/9781492076322/\" target=\"_blank\">Cloud Native Go</a> by Matthew Titmus, which gives a smooth introduction to the cloud native world using the benefits of Go. The book starts with Go basics and cloud native patterns, and that&#39;s where I thought &#34;I should write about these patterns!&#34;.</p>\n<p>In this series of blog posts, I will write about the cloud native patterns I&#39;ve learnt – also with illustrations using <a href=\"https://www.manim.community\" target=\"_blank\">Manim</a>.</p>\n<h2 id=\"the-problem\">The Problem</h2>\n<p>Let&#39;s say we have a constant data source (such as a Go <a href=\"https://go.dev/tour/concurrency/2\" target=\"_blank\">channel</a>), and we need to process the data and put the processed data into a destination channel with a latency as low as possible.</p>\n<p>In the general case, we have a processor function which is in the middle of source and destinations, which processes the data packets (packet here is an abstraction for simplicity) one by one.</p>\n<p><img src=\"/assets/articles/fan-in-fan-out-1.png\" alt=\"\" loading=\"lazy\"/></p>\n<p>However, every processing function have latency. This may be because of network or CPU usage, blocking syscalls, etc. If we send enough packets per second to the processor function, voilà! We now have a bottleneck!</p>\n<p><img src=\"/assets/articles/fan-in-fan-out-2.png\" alt=\"\" loading=\"lazy\"/></p>\n<h2 id=\"solution\">Solution</h2>\n<p>There&#39;s a fairly simple solution to this problem: using multiple processors inside the data pipeline. This way, we can process the data stream concurrently, which drops the overall latency and decreases the pipeline congestion.</p>\n<p><img src=\"/assets/articles/fan-in-fan-out-3.png\" alt=\"\" loading=\"lazy\"/></p>\n<h2 id=\"thats-where-fan-in-and-fan-out-comes-in\">That&#39;s where Fan-in and Fan-out comes in…</h2>\n<p>We can implement this solution by utilizing shared memory, such as message queues.<br/>\nWith this approach, we will split the incoming data packets into different input queues. Then, each queue&#39;s own processor will take the packets one by one, process the data, and put the processed data into its related output queue. Finally, the destination (another processor, queue, or some other system) will take the processed data packets from each of the output queues, and aggregate them into a single data source.</p>\n<p>The first approach, splitting the data source (input) to multiple data sources (input queues) is called the <code>Fan-out</code> pattern. The second one, aggregating multiple data sources (output queues) into a single data source (destination) is called the <code>Fan-in</code> pattern.</p>\n<blockquote>\n<p>For simplicity, we&#39;ve specified one input queue and one output queue for each processor in our pipeline. We could use multiple input/output queues per processor, or a shared queue between a few processors, depending on the overall system requirements.</p>\n</blockquote>\n<p><img src=\"/assets/articles/fan-in-fan-out-4.png\" alt=\"\" loading=\"lazy\"/></p>\n<h2 id=\"go-implementation\">Go Implementation</h2>\n<p>Let&#39;s get our hands dirty with some concurrent Go! First, let&#39;s define our data sources:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">stringGenerator</span><span style=\"\">(</span><span style=\"\">prefix</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">count</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uint</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">ch</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">close</span><span style=\"\">(</span><span style=\"\">ch</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">uint</span><span style=\"\">(</span><span style=\"color:#bd93f9\">0</span><span style=\"\">);</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"\">count</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">            </span><span style=\"\">ch</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\"> </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sprintf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s-%d&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">prefix</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">ch</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>The function <code>stringGenerator</code> creates a receive-only string channel, creates a <a href=\"https://go.dev/tour/concurrency/1\" target=\"_blank\">goroutine</a> that puts prefixed strings into the channel, and returns the channel. We read from this channel later in the Fan-out code.</p>\n<p>Our processor function will be fairly simple too:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">stringProcessor</span><span style=\"\">(</span><span style=\"\">id</span><span style=\"\"> </span><span style=\"color:#8be9fd\">int</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">source</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">ch</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">close</span><span style=\"\">(</span><span style=\"\">ch</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">source</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">            </span><span style=\"\">ch</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\"> </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sprintf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;P-%d processed message: %s&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">id</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">            </span><span style=\"\">millisecs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">rand</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Intn</span><span style=\"\">(</span><span style=\"color:#bd93f9\">901</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">            </span><span style=\"\">time</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sleep</span><span style=\"\">(</span><span style=\"\">time</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Duration</span><span style=\"\">(</span><span style=\"\">millisecs</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">int</span><span style=\"\">(</span><span style=\"\">time</span><span style=\"\">.</span><span style=\"\">Millisecond</span><span style=\"\">)))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">ch</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>Inside the processor function, we will wait for a random while to simulate the processor latency.</p>\n<h3 id=\"fan-out-implementation\">Fan-out Implementation</h3>\n<p>In the Fan-out implementation, we will take a receive-only channel, and return a slice of receive-only channels:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">// Splitter implements the Fan-out pattern\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Splitter</span><span style=\"\">(</span><span style=\"\">source</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">numDests</span><span style=\"\"> </span><span style=\"color:#8be9fd\">uint</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"\">destinations</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">([]</span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">numDests</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">uint</span><span style=\"\">(</span><span style=\"color:#bd93f9\">0</span><span style=\"\">);</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\"> </span><span style=\"\">&lt;</span><span style=\"\"> </span><span style=\"\">numDests</span><span style=\"\">;</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"color:#ff79c6\">++</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">        </span><span style=\"\">dest</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">close</span><span style=\"\">(</span><span style=\"\">dest</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">source</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">                </span><span style=\"\">dest</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">            </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">        </span><span style=\"\">destinations</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">destinations</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">dest</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">destinations</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>Goroutines created inside the <code>Splitter</code> function will handle the data routing logic. Notice that inside the goroutines, we used a single <code>range</code> statement to receive from the <code>source</code> channel:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">source</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">dest</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>This means each goroutine will try to read from the channel in the loop, and the first one to do the read will receive the next item. In other words, <strong>each goroutine will fight over the next data instance</strong>.</p>\n<p>We could use a centralized solution for Fan-out instead of competing goroutines. In that case, we would define a <code>master process</code> to distribute each incoming data instance (<code>string</code> in our case) among all the output channels.</p>\n<h3 id=\"fan-in-implementation\">Fan-in Implementation</h3>\n<p>In Fan-in, we will basically do the reverse of Fan-out, with a few differences:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#6272a4\">// Aggregator implements the Fan-in pattern\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Aggregator</span><span style=\"\">(</span><span style=\"\">sources</span><span style=\"\"> </span><span style=\"\">[]</span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"\">destination</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">wg</span><span style=\"\"> </span><span style=\"\">sync</span><span style=\"\">.</span><span style=\"\">WaitGroup</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">    </span><span style=\"\">wg</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Add</span><span style=\"\">(</span><span style=\"color:#8be9fd;font-style:italic\">len</span><span style=\"\">(</span><span style=\"\">sources</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">_</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">source</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">sources</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">(</span><span style=\"\">src</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">defer</span><span style=\"\"> </span><span style=\"\">wg</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Done</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">src</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">                </span><span style=\"\">destination</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"\"> </span><span style=\"\">data</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">            </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}(</span><span style=\"\">source</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">go</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">        </span><span style=\"\">wg</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Wait</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#8be9fd;font-style:italic\">close</span><span style=\"\">(</span><span style=\"\">destination</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">destination</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>The <code>Aggregator</code> function takes a slice of receive-only input sources and returns a single receive-only output channel. Inside, we created a goroutine for each input source, which reads from the source continuously and populates the output channel (<code>destination</code>) with the data it received.</p>\n<p>Notice that we&#39;ve used a <code>sync.WaitGroup</code> to wait for the aggregator goroutines to finish. After an input source (<code>channel</code>) is closed, the for loop inside the respective goroutine will end, and it will finish its job.</p>\n<p>After all input sources are closed, we&#39;re done with aggregating, and we now can close the destination channel. <strong>This is a crucial step</strong>, and if we don&#39;t close the channel we have created, the Go runtime will complain with a fatal error:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">fatal error: all goroutines are asleep - deadlock!\n</span></span></span></code></pre><h3 id=\"main\">main()</h3>\n<p>Putting all of our functions together, we&#39;re ready to run our code:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">const</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">processorCount</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#bd93f9\">10</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\"></span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">main</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">    </span><span style=\"\">splitSources</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Splitter</span><span style=\"\">(</span><span style=\"color:#50fa7b\">stringGenerator</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;test&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">100</span><span style=\"\">),</span><span style=\"\"> </span><span style=\"\">processorCount</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">    </span><span style=\"\">procSources</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">make</span><span style=\"\">([]</span><span style=\"color:#ff79c6\">&lt;-</span><span style=\"color:#8be9fd;font-style:italic\">chan</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#bd93f9\">0</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">processorCount</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">i</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">src</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">splitSources</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">        </span><span style=\"\">procSources</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">procSources</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#50fa7b\">stringProcessor</span><span style=\"\">(</span><span style=\"\">i</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">src</span><span style=\"\">))</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">out</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Aggregator</span><span style=\"\">(</span><span style=\"\">procSources</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">        </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Println</span><span style=\"\">(</span><span style=\"\">out</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><h2 id=\"tldr\">tl;dr</h2>\n<ul>\n<li>Data pipelines with a single processor will eventually bump into a bottleneck</li>\n<li>Splitting the input source into several queues and processing concurrently is helpful</li>\n<li>This split-process-aggregate pattern is called Fan-in/Fan-out</li>\n</ul>\n<p>Thank you for reading!</p>\n",
            "url": "https://sazak.io/articles/cloud-native-patterns-illustrated-fan-in-and-fan-out-2022-10-30",
            "title": "Cloud Native Patterns Illustrated: Fan-in and Fan-out",
            "summary": "Fan-in and fan-out patterns explained with fancy animations.",
            "image": "https://sazak.io/assets/articles/cloud-native-patterns-illustrated-fan-in-and-fan-out-2022-10-30.jpeg",
            "date_modified": "2022-10-30T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/articles/gls-file-manager-on-terminal-with-go-2022-07-19",
            "content_html": "<p>This week my last term in college is finished and my brain started to come up with creative ides, so I started working on one of the fancy ones: developing a file manager with GUI that I can use in terminal, with Go.</p>\n<p>Before diving into my design and development process, here’s a little backstory: I use a 2019 model MacBook Pro storage as my development machine. Since it only has 256 GB storage, I frequently run out of space and try to find which files take up most of the space and which of them to delete.  Here I have a few options and the one I do is basically using <code>du</code> command to find out the biggest files on terminal:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">$ du -shc ~/* </span><span style=\"\">|</span><span style=\"\"> sort -rh\n</span></span></span></code></pre><p>This basically works out, but I find myself consistently bragging about <code>du</code> not having an interactive interface that also lists the filesystem in tree format with file/folder sizes.</p>\n<p>And that’s where I said out loud: I should do this!</p>\n<h2 id=\"the-initial-design\">The initial design</h2>\n<p>After deciding to develop a program for this idea, I thought of the main features this program should provide for my daily use:</p>\n<ul>\n<li>List files and folders under a specified path in tree view</li>\n<li>Show total size of the file/folder in KB, MB, GB, etc.</li>\n<li>Show file type (MIME and file extension) as the <code>file</code> command does</li>\n<li>Show file/folder permissions</li>\n<li>Optionally show last modification or creation time of files</li>\n<li>Search files by name with regular expressions</li>\n<li>Create (<code>touch</code>-like), move, copy, remove files</li>\n<li>Open files with the default or specified program</li>\n</ul>\n<p>Many other features could be added, but these are the trivial ones :) I also decided to name my program <code>gls</code>, a mimicking <code>“graphical ls”</code>.</p>\n<p><img src=\"/assets/articles/Screen%20Shot%202022-07-10%20at%2010.40.33.png\" alt=\"Initial UI design of gls that I&#39;ve drawn on iPad\" loading=\"lazy\"/></p>\n<h2 id=\"walking-down-the-filesystem\">Walking down the filesystem</h2>\n<p>Before diving deep into coding the UI, we first need to build a virtual filesystem representation of the original folder structure with the path we’re currently interested in. This representation will make us able to show the real folder structure in the UI in tree view. It will also help us perform specific file- and folder-related operations, such as copying and removing, by using the virtual representation to get info of specific files and folders instead of using system calls to get the same information each time.</p>\n<p>Speaking of which, most of the operating systems hold the whole filesystem structure as a one-rooted tree data structure, where all folders and files are child nodes of the root node or another node with a higher-level parent node. This type of data structure is also called “directed acyclic graph”.</p>\n<p><img src=\"/assets/articles/Screen%20Shot%202022-07-10%20at%2010.39.22.png\" alt=\"An example file tree in UNIX-like filesystem format\" loading=\"lazy\"/></p>\n<blockquote data-quote-character=\"gopher-info-2\" class=\"quote-character\"><p> Extra information: in Linux and UNIX-like systems, every node in the filesystem tree is a file<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup>. Even directories, drivers (files under <code>/dev</code>), terminals (eg. <code>/dev/tty</code>), etc. are files with special properties.</p>\n</blockquote>\n<p>Coming back to our virtual filesystem representation, it will be sufficient to construct a basic tree data structure that you’ve probably coded from scratch in a DS course:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">Node</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Name</span><span style=\"\">             </span><span style=\"color:#8be9fd\">string</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Mode</span><span style=\"\">             </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"\">FileMode</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Size</span><span style=\"\">             </span><span style=\"color:#8be9fd\">int64</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">    </span><span style=\"\">SizeOnDisk</span><span style=\"\">       </span><span style=\"color:#8be9fd\">int64</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">    </span><span style=\"\">IsDir</span><span style=\"\">            </span><span style=\"color:#8be9fd\">bool</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">    </span><span style=\"\">LastModification</span><span style=\"\"> </span><span style=\"\">time</span><span style=\"\">.</span><span style=\"\">Time</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Children</span><span style=\"\">         </span><span style=\"\">[]</span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Parent</span><span style=\"\">           </span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><blockquote data-quote-character=\"gopher-info\" class=\"quote-character\"><p> You may be asking “Why <code>Size</code> is a signed integer while it’s used for the size of an entity which can’t be negative?”. Well, the answer is <code>os.FileInfo</code>’s size property is also <code>int64</code> and that’s also probably because of why <code>len()</code> returns a signed integer, to prevent integer underflows in arithmetic calculations<sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup>. Also, storing the size in <code>int64</code> makes us able to properly store the size of files/folders <em>up to 16777216 TB</em>, so it’s actually not a downside to use signed integers here.</p>\n</blockquote>\n<p>The reason that we have both <code>Size</code> and <code>SizeOnDisk</code> is that, <code>Size</code> shows the actual number of bytes a specific file consists of. But as the operating systems allocates a number of blocks on the storage device for each file, the real size on the disk is a multiple of <code>block_size</code><sup id=\"fnref:3\"><a href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\">3</a></sup> (Even if the file content is a single byte, the size of the storage area allocated for the file will be <code>block_size</code> bytes<sup id=\"fnref:4\"><a href=\"#fn:4\" class=\"footnote-ref\" role=\"doc-noteref\">4</a></sup>). So we calculate <code>SizeOnDisk</code> by <code>block_size * number_of_blocks</code>.</p>\n<p>Now it’s time to walk on the file tree. To do this, we need to use a tree traversal algorithm<sup id=\"fnref:5\"><a href=\"#fn:5\" class=\"footnote-ref\" role=\"doc-noteref\">5</a></sup>, which are pretty straightforward. I will explain the traversal basics in the next subtitle, so you can pass it if it’s too basic for you.</p>\n<h3 id=\"primer-on-tree-traversals\">Primer on tree traversals</h3>\n<p>The most trivial tree traversal algorithm is depth-first search, where we walk down the tree from a node as deep as possible before hopping to its siblings. DFS can be used as pre-order, post-order and in-order. The only difference is when do we process the root (or current) node, other than that, what DFS does is iteratively applying the same traversal to the child subtrees of the specific node.</p>\n<p>In pre-order traversal, we visit the root node and then the children one by one (root-Left-Right for example if we have a binary tree). In post-order, we visit the children one by one and then the root node eventually (e.g L-R-root). Likewise in in-order traversal we visit the root node in between visiting the child nodes (e.g L-root-R).</p>\n<p><img src=\"/assets/articles/IMG_B1947371A873-1.jpeg\" alt=\"Node visiting order visualization in the same binary tree using post-order (left) and pre-order (right) algorithms\" loading=\"lazy\"/></p>\n<h3 id=\"coding-the-traversal-function\">Coding the traversal function</h3>\n<p>For the sake of implementation simplicity, I decided to use pre-order traversal to walk in the file tree and construct the <code>*Node</code> tree on our side.</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 1</span><span style=\"\"><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Walk</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd\">error</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 2</span><span style=\"\"><span style=\"\">    </span><span style=\"\">f</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Lstat</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 3</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 4</span><span style=\"\"><span style=\"\">        </span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Warningf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s: %v&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">path</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 5</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 6</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 7</span><span style=\"\"><span style=\"\">    </span><span style=\"\">st</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sys</span><span style=\"\">().(</span><span style=\"color:#ff79c6\">*</span><span style=\"\">syscall</span><span style=\"\">.</span><span style=\"\">Stat_t</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 8</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">!</span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 9</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Errorf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;could not cast %T to syscall.Stat_t&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sys</span><span style=\"\">())</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">10</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">11</span><span style=\"\"><span style=\"\">    </span><span style=\"\">root</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">Node</span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">12</span><span style=\"\"><span style=\"\">        </span><span style=\"\">Name</span><span style=\"\">:</span><span style=\"\">             </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Name</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">13</span><span style=\"\"><span style=\"\">        </span><span style=\"\">Mode</span><span style=\"\">:</span><span style=\"\">             </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Mode</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">14</span><span style=\"\"><span style=\"\">        </span><span style=\"\">Size</span><span style=\"\">:</span><span style=\"\">             </span><span style=\"\">st</span><span style=\"\">.</span><span style=\"\">Size</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">15</span><span style=\"\"><span style=\"\">        </span><span style=\"\">SizeOnDisk</span><span style=\"\">:</span><span style=\"\">       </span><span style=\"\">st</span><span style=\"\">.</span><span style=\"\">Blocks</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\"> </span><span style=\"color:#bd93f9\">512</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">16</span><span style=\"\"><span style=\"\">        </span><span style=\"\">IsDir</span><span style=\"\">:</span><span style=\"\">            </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">IsDir</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">17</span><span style=\"\"><span style=\"\">        </span><span style=\"\">LastModification</span><span style=\"\">:</span><span style=\"\"> </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">ModTime</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">18</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">19</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">IsDir</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">20</span><span style=\"\"><span style=\"\">        </span><span style=\"\">names</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">readDirNames</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">21</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">22</span><span style=\"\"><span style=\"\">            </span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Warningf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s: %v&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">path</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">23</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">24</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">25</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">_</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">name</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">names</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">26</span><span style=\"\"><span style=\"\">            </span><span style=\"\">child</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Walk</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;/&#34;</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"\">name</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">27</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">28</span><span style=\"\"><span style=\"\">                </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">29</span><span style=\"\"><span style=\"\">            </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">30</span><span style=\"\"><span style=\"\">            </span><span style=\"\">child</span><span style=\"\">.</span><span style=\"\">Parent</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">31</span><span style=\"\"><span style=\"\">            </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">Size</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+=</span><span style=\"\"> </span><span style=\"\">child</span><span style=\"\">.</span><span style=\"\">Size</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">32</span><span style=\"\"><span style=\"\">            </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">SizeOnDisk</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+=</span><span style=\"\"> </span><span style=\"\">child</span><span style=\"\">.</span><span style=\"\">SizeOnDisk</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">33</span><span style=\"\"><span style=\"\">            </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">Children</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">Children</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">child</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">34</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">35</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">36</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">37</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>We call <code>os.Lstat</code> for each node in the file tree to get the file/directory information. The <code>os.Lstat</code> function uses the <code>lstat</code><sup id=\"fnref:6\"><a href=\"#fn:6\" class=\"footnote-ref\" role=\"doc-noteref\">6</a></sup> system call internally, which returns <code>struct stat</code> structure. Then,  <code>os.Lstat</code> uses  <code>struct stat</code> to return <code>os.FileInfo</code>, which is an easily usable variant of <code>struct stat</code>.</p>\n<p>After getting the file information, we construct the root node of type <code>*Node</code>, and then call <code>Walk</code> for each of its children if root is a directory, and lastly update the child nodes’ root, the root’s size and so on. Children of the root are found by the <code>readDirNames</code> function, which basically reads the directories under the specified path and sorts them by their name<sup id=\"fnref:7\"><a href=\"#fn:7\" class=\"footnote-ref\" role=\"doc-noteref\">7</a></sup>. The <code>SizeOnDisk</code> calculation is done by using <code>Stat_t.Blocks</code>. The <code>Stat_t</code> structure is the Go equivalent of Linux kernel’s <code>struct stat</code>, and <code>Stat_t.Blocks</code> is the number of 512-byte blocks that the file uses.</p>\n<blockquote data-quote-character=\"beaver-question\" class=\"quote-character\"><p> Please note that this code we’ve written will only work in Linux and UNIX-like systems!</p>\n</blockquote>\n<p>We can now call <code>Walk</code> and test it on a real directory:</p>\n<pre data-language=\"go\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  1</span><span style=\"\"><span style=\"color:#ff79c6\">import</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  2</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;flag&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  3</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;fmt&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  4</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;os&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  5</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;sort&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  6</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;strings&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  7</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;syscall&#34;</span><span style=\"\"> \n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  8</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;time&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">  9</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 10</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#f1fa8c\">&#34;github.com/ozansz/gls/log&#34;</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 11</span><span style=\"\"><span style=\"\"></span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 12</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 13</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">type</span><span style=\"\"> </span><span style=\"\">Node</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">struct</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 14</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Name</span><span style=\"\">             </span><span style=\"color:#8be9fd\">string</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 15</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Mode</span><span style=\"\">             </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"\">FileMode</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 16</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Size</span><span style=\"\">             </span><span style=\"color:#8be9fd\">int64</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 17</span><span style=\"\"><span style=\"\">    </span><span style=\"\">SizeOnDisk</span><span style=\"\">       </span><span style=\"color:#8be9fd\">int64</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 18</span><span style=\"\"><span style=\"\">    </span><span style=\"\">IsDir</span><span style=\"\">            </span><span style=\"color:#8be9fd\">bool</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 19</span><span style=\"\"><span style=\"\">    </span><span style=\"\">LastModification</span><span style=\"\"> </span><span style=\"\">time</span><span style=\"\">.</span><span style=\"\">Time</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 20</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Children</span><span style=\"\">         </span><span style=\"\">[]</span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 21</span><span style=\"\"><span style=\"\">    </span><span style=\"\">Parent</span><span style=\"\">           </span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 22</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 23</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 24</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">n</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Print</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 25</span><span style=\"\"><span style=\"\">    </span><span style=\"\">n</span><span style=\"\">.</span><span style=\"color:#50fa7b\">printWithLevel</span><span style=\"\">(</span><span style=\"color:#bd93f9\">0</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 26</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 27</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 28</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">n</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"color:#50fa7b\">printWithLevel</span><span style=\"\">(</span><span style=\"\">level</span><span style=\"\"> </span><span style=\"color:#8be9fd\">int</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 29</span><span style=\"\"><span style=\"\">    </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Printf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s%s [%s] [%d]\\n&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">strings</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Repeat</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;  &#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">level</span><span style=\"\">),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 30</span><span style=\"\"><span style=\"\">        </span><span style=\"\">n</span><span style=\"\">.</span><span style=\"\">Name</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">n</span><span style=\"\">.</span><span style=\"\">Mode</span><span style=\"\">.</span><span style=\"color:#50fa7b\">String</span><span style=\"\">(),</span><span style=\"\"> </span><span style=\"\">n</span><span style=\"\">.</span><span style=\"\">SizeOnDisk</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 31</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">_</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">child</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">n</span><span style=\"\">.</span><span style=\"\">Children</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 32</span><span style=\"\"><span style=\"\">        </span><span style=\"\">child</span><span style=\"\">.</span><span style=\"color:#50fa7b\">printWithLevel</span><span style=\"\">(</span><span style=\"\">level</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 33</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 34</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 35</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 36</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">var</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 37</span><span style=\"\"><span style=\"\">    </span><span style=\"\">path</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">flag</span><span style=\"\">.</span><span style=\"color:#50fa7b\">String</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;path&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;path to walk&#34;</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 38</span><span style=\"\"><span style=\"\"></span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 39</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 40</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">main</span><span style=\"\">()</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 41</span><span style=\"\"><span style=\"\">    </span><span style=\"\">flag</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Parse</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 42</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\">path</span><span style=\"\"> </span><span style=\"color:#ff79c6\">==</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;&#34;</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 43</span><span style=\"\"><span style=\"\">        </span><span style=\"\">flag</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Usage</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 44</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 45</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 46</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 47</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 48</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 49</span><span style=\"\"><span style=\"\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Walk</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">(</span><span style=\"color:#ff79c6\">*</span><span style=\"\">Node</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd\">error</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 50</span><span style=\"\"><span style=\"\">    </span><span style=\"\">f</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Lstat</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 51</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 52</span><span style=\"\"><span style=\"\">        </span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Warningf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s: %v&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">path</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 53</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 54</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 55</span><span style=\"\"><span style=\"\">    </span><span style=\"\">st</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sys</span><span style=\"\">().(</span><span style=\"color:#ff79c6\">*</span><span style=\"\">syscall</span><span style=\"\">.</span><span style=\"\">Stat_t</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 56</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">!</span><span style=\"\">ok</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 57</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">fmt</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Errorf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;could not cast %T to syscall.Stat_t&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Sys</span><span style=\"\">())</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 58</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 59</span><span style=\"\"><span style=\"\">    </span><span style=\"\">root</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">&amp;</span><span style=\"\">Node</span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 60</span><span style=\"\"><span style=\"\">        </span><span style=\"\">Name</span><span style=\"\">:</span><span style=\"\">             </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Name</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 61</span><span style=\"\"><span style=\"\">        </span><span style=\"\">Mode</span><span style=\"\">:</span><span style=\"\">             </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Mode</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 62</span><span style=\"\"><span style=\"\">        </span><span style=\"\">Size</span><span style=\"\">:</span><span style=\"\">             </span><span style=\"\">st</span><span style=\"\">.</span><span style=\"\">Size</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 63</span><span style=\"\"><span style=\"\">        </span><span style=\"\">SizeOnDisk</span><span style=\"\">:</span><span style=\"\">       </span><span style=\"\">st</span><span style=\"\">.</span><span style=\"\">Blocks</span><span style=\"\"> </span><span style=\"color:#ff79c6\">*</span><span style=\"\"> </span><span style=\"color:#bd93f9\">512</span><span style=\"\">,</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 64</span><span style=\"\"><span style=\"\">        </span><span style=\"\">IsDir</span><span style=\"\">:</span><span style=\"\">            </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">IsDir</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 65</span><span style=\"\"><span style=\"\">        </span><span style=\"\">LastModification</span><span style=\"\">:</span><span style=\"\"> </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">ModTime</span><span style=\"\">(),</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 66</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 67</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">IsDir</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 68</span><span style=\"\"><span style=\"\">        </span><span style=\"\">names</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">readDirNames</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 69</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 70</span><span style=\"\"><span style=\"\">            </span><span style=\"\">log</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Warningf</span><span style=\"\">(</span><span style=\"color:#f1fa8c\">&#34;%s: %v&#34;</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">path</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 71</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 72</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 73</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">for</span><span style=\"\"> </span><span style=\"\">_</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">name</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">range</span><span style=\"\"> </span><span style=\"\">names</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 74</span><span style=\"\"><span style=\"\">            </span><span style=\"\">child</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"color:#50fa7b\">Walk</span><span style=\"\">(</span><span style=\"\">path</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"color:#f1fa8c\">&#34;/&#34;</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+</span><span style=\"\"> </span><span style=\"\">name</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 75</span><span style=\"\"><span style=\"\">            </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 76</span><span style=\"\"><span style=\"\">                </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 77</span><span style=\"\"><span style=\"\">            </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 78</span><span style=\"\"><span style=\"\">            </span><span style=\"\">child</span><span style=\"\">.</span><span style=\"\">Parent</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 79</span><span style=\"\"><span style=\"\">            </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">Size</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+=</span><span style=\"\"> </span><span style=\"\">child</span><span style=\"\">.</span><span style=\"\">Size</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 80</span><span style=\"\"><span style=\"\">            </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">SizeOnDisk</span><span style=\"\"> </span><span style=\"color:#ff79c6\">+=</span><span style=\"\"> </span><span style=\"\">child</span><span style=\"\">.</span><span style=\"\">SizeOnDisk</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 81</span><span style=\"\"><span style=\"\">            </span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">Children</span><span style=\"\"> </span><span style=\"\">=</span><span style=\"\"> </span><span style=\"color:#8be9fd;font-style:italic\">append</span><span style=\"\">(</span><span style=\"\">root</span><span style=\"\">.</span><span style=\"\">Children</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">child</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 82</span><span style=\"\"><span style=\"\">        </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 83</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 84</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">root</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 85</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 86</span><span style=\"\"><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 87</span><span style=\"\"><span style=\"\"></span><span style=\"color:#6272a4\">// Taken directly from the Go stdlib\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 88</span><span style=\"\"><span style=\"color:#6272a4\"></span><span style=\"color:#8be9fd;font-style:italic\">func</span><span style=\"\"> </span><span style=\"color:#50fa7b\">readDirNames</span><span style=\"\">(</span><span style=\"\">dirname</span><span style=\"\"> </span><span style=\"color:#8be9fd\">string</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">([]</span><span style=\"color:#8be9fd\">string</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#8be9fd\">error</span><span style=\"\">)</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 89</span><span style=\"\"><span style=\"\">    </span><span style=\"\">f</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">os</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Open</span><span style=\"\">(</span><span style=\"\">dirname</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 90</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 91</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 92</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 93</span><span style=\"\"><span style=\"\">    </span><span style=\"\">names</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">:=</span><span style=\"\"> </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Readdirnames</span><span style=\"\">(</span><span style=\"color:#ff79c6\">-</span><span style=\"color:#bd93f9\">1</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 94</span><span style=\"\"><span style=\"\">    </span><span style=\"\">f</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Close</span><span style=\"\">()</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 95</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">if</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\"> </span><span style=\"color:#ff79c6\">!=</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\"> </span><span style=\"\">{</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 96</span><span style=\"\"><span style=\"\">        </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"\">err</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 97</span><span style=\"\"><span style=\"\">    </span><span style=\"\">}</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 98</span><span style=\"\"><span style=\"\">    </span><span style=\"\">sort</span><span style=\"\">.</span><span style=\"color:#50fa7b\">Strings</span><span style=\"\">(</span><span style=\"\">names</span><span style=\"\">)</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\"> 99</span><span style=\"\"><span style=\"\">    </span><span style=\"color:#ff79c6\">return</span><span style=\"\"> </span><span style=\"\">names</span><span style=\"\">,</span><span style=\"\"> </span><span style=\"color:#ff79c6\">nil</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">100</span><span style=\"\"><span style=\"\"></span><span style=\"\">}</span><span style=\"\">\n</span></span></span></code></pre><p>When we save this code as <code>main.go</code> and run it by specifying a path,</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">$ go run main.go --path ~/root-folder\n</span></span></span></code></pre><p>…and assume that the file tree is something like that:</p>\n<p><img src=\"/assets/articles/Screen%20Shot%202022-07-10%20at%2010.38.48.png\" alt=\"Example file tree for the Walk function test\" loading=\"lazy\"/></p>\n<p>…we will see an output like that:</p>\n<pre data-language=\"bash\" tabindex=\"0\" style=\"color:#f8f8f2;background-color:#282a36;\"><code><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">1</span><span style=\"\"><span style=\"\">root-folder </span><span style=\"color:#ff79c6\">[</span><span style=\"\">drwxr-xr-x</span><span style=\"color:#ff79c6\">]</span><span style=\"\"> </span><span style=\"color:#ff79c6\">[</span><span style=\"\">10010624</span><span style=\"color:#ff79c6\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">2</span><span style=\"\"><span style=\"\">  subfolder </span><span style=\"color:#ff79c6\">[</span><span style=\"\">drwxr-xr-x</span><span style=\"color:#ff79c6\">]</span><span style=\"\"> </span><span style=\"color:#ff79c6\">[</span><span style=\"\">10002432</span><span style=\"color:#ff79c6\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">3</span><span style=\"\"><span style=\"\">    file_3.mp4 </span><span style=\"color:#ff79c6\">[</span><span style=\"\">-rw-r--r--</span><span style=\"color:#ff79c6\">]</span><span style=\"\"> </span><span style=\"color:#ff79c6\">[</span><span style=\"\">9998336</span><span style=\"color:#ff79c6\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">4</span><span style=\"\"><span style=\"\">  file_1.c </span><span style=\"color:#ff79c6\">[</span><span style=\"\">-rw-rw-r</span><span style=\"color:#ff79c6\">]</span><span style=\"\"> </span><span style=\"color:#ff79c6\">[</span><span style=\"\">8192</span><span style=\"color:#ff79c6\">]</span><span style=\"\">\n</span></span></span><span style=\"display:flex;\"><span style=\"white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f\">5</span><span style=\"\"><span style=\"\">  file_2.sh </span><span style=\"color:#ff79c6\">[</span><span style=\"\">-rw-r---</span><span style=\"color:#ff79c6\">]</span><span style=\"\"> </span><span style=\"color:#ff79c6\">[</span><span style=\"\">4096</span><span style=\"color:#ff79c6\">]</span><span style=\"\">\n</span></span></span></code></pre><div class=\"footnotes\" role=\"doc-endnotes\">\n<hr/>\n<ol>\n<li id=\"fn:1\" data-index=\"1\">\n<p><a href=\"https://en.wikipedia.org/wiki/Unix_filesystem\">https://en.wikipedia.org/wiki/Unix_filesystem</a> <a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:2\" data-index=\"2\">\n<p><a href=\"https://stackoverflow.com/questions/39088945/why-does-len-returned-a-signed-value\">https://stackoverflow.com/questions/39088945/why-does-len-returned-a-signed-value</a> <a href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:3\" data-index=\"3\">\n<p><a href=\"https://wiki.linuxquestions.org/wiki/Block_devices_and_block_sizes\">https://wiki.linuxquestions.org/wiki/Block_devices_and_block_sizes</a> <a href=\"#fnref:3\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:4\" data-index=\"4\">\n<p><a href=\"https://tldp.org/LDP/sag/html/filesystems.html\">https://tldp.org/LDP/sag/html/filesystems.html</a> <a href=\"#fnref:4\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:5\" data-index=\"5\">\n<p><a href=\"https://en.wikipedia.org/wiki/Tree_traversal\">https://en.wikipedia.org/wiki/Tree_traversal</a> <a href=\"#fnref:5\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:6\" data-index=\"6\">\n<p><a href=\"https://man7.org/linux/man-pages/man2/lstat.2.html\">https://man7.org/linux/man-pages/man2/lstat.2.html</a> <a href=\"#fnref:6\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:7\" data-index=\"7\">\n<p><a href=\"https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/path/filepath/path.go;l=543\">https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/path/filepath/path.go;l=543</a> <a href=\"#fnref:7\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>\n",
            "url": "https://sazak.io/articles/gls-file-manager-on-terminal-with-go-2022-07-19",
            "title": "gls: File Manager on Terminal with Go",
            "summary": "I coded a graphical ls command with folder sizes in Go.",
            "image": "https://sazak.io/assets/articles/gls-file-manager-on-terminal-with-go-2022-07-19.jpeg",
            "date_modified": "2022-07-19T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        },
        {
            "id": "https://sazak.io/talks/continuous-profiling-with-go-2022-06-17",
            "content_html": "<p>I talked about continuous profiling with Go, and how to use the pprof package to profile Go programs at Ankara Gophers&#39;s 8th meetup.</p>\n<p>Ankara Gophers is a local Go community in Ankara, Turkey. They organize meetups to bring Go developers together, and to share knowledge and experiences since 2022.</p>\n<blockquote>\n<p>Unfortunately the event recording or slides are not available.</p>\n</blockquote>\n",
            "url": "https://sazak.io/talks/continuous-profiling-with-go-2022-06-17",
            "title": "Continuous Profiling with Go",
            "summary": "Talked about continuous profiling with Go at Ankara Gophers meetup. Ankara Gophers is a local Go community in Ankara, Turkey.",
            "image": "https://sazak.io/assets/talks/continuous-profiling-with-go-2022-06-17.jpeg",
            "date_modified": "2022-06-17T00:00:00.000Z",
            "author": {
                "name": "Ozan Sazak",
                "url": "https://sazak.io"
            }
        }
    ]
}