<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashwin Gopalsamy</title>
    <description>The latest articles on DEV Community by Ashwin Gopalsamy (@ashwingopalsamy).</description>
    <link>https://dev.to/ashwingopalsamy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1920945%2F83ec5409-92f8-41cc-b80e-86e5e510d9d5.jpg</url>
      <title>DEV Community: Ashwin Gopalsamy</title>
      <link>https://dev.to/ashwingopalsamy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashwingopalsamy"/>
    <language>en</language>
    <item>
      <title>How Internet works?</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Fri, 07 Nov 2025 03:43:26 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/how-internet-works-43po</link>
      <guid>https://dev.to/ashwingopalsamy/how-internet-works-43po</guid>
      <description>&lt;h2&gt;
  
  
  🌐 How the Internet actually works
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Local Devices&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Phones, tablets, and laptops connect to the internet through &lt;strong&gt;Wi-Fi&lt;/strong&gt;, &lt;strong&gt;broadband&lt;/strong&gt;, or &lt;strong&gt;mobile data&lt;/strong&gt;. These create the &lt;em&gt;entry point&lt;/em&gt; for communication.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. &lt;strong&gt;Internet Service Provider (ISP)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The ISP’s network (cell towers or broadband routers) assigns your device an &lt;strong&gt;IP address&lt;/strong&gt; and routes your data.&lt;/p&gt;

&lt;p&gt;ISPs act as your &lt;strong&gt;gateway&lt;/strong&gt; to the wider internet.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;DNS (Domain Name System)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you enter a website (like &lt;code&gt;www.google.com&lt;/code&gt;), your device first performs a &lt;strong&gt;DNS lookup&lt;/strong&gt; to translate the domain name into an &lt;strong&gt;IP address&lt;/strong&gt; (like &lt;code&gt;142.250.190.14&lt;/code&gt;).&lt;/p&gt;




&lt;h3&gt;
  
  
  4. &lt;strong&gt;IXP (Internet Exchange Point)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;ISPs don’t directly connect to every network. They pass traffic through &lt;strong&gt;IXPs&lt;/strong&gt;, where multiple ISPs and large networks exchange data.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. &lt;strong&gt;BGP &amp;amp; Autonomous Systems&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Border Gateway Protocol (BGP)&lt;/strong&gt; connects independent networks called &lt;strong&gt;Autonomous Systems (AS)&lt;/strong&gt; — the internet’s “routing map.”&lt;/p&gt;

&lt;p&gt;This system decides how data travels across the globe through the most efficient or available path.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. &lt;strong&gt;Servers &amp;amp; Data Centers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Your request eventually reaches a &lt;strong&gt;server&lt;/strong&gt; (or cluster of servers) hosting the target website or service.&lt;/p&gt;

&lt;p&gt;These servers process your request and send back a response (like a web page, video, or API data).&lt;/p&gt;




&lt;h3&gt;
  
  
  7. &lt;strong&gt;CDN Nodes (Content Delivery Networks)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To speed things up, &lt;strong&gt;CDNs&lt;/strong&gt; store cached content (like images or videos) in servers closer to your location — often inside or near ISP networks.&lt;/p&gt;




&lt;h3&gt;
  
  
  8. &lt;strong&gt;Return Path&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The response travels back through the &lt;strong&gt;same or similar route&lt;/strong&gt; — from server → BGP → IXP → ISP → your device — and your browser/app displays the result.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧩 In Short:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Device → ISP → DNS → IXP → BGP/AS Backbone → Server/CDN → back to Device&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each layer plays a distinct role:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DNS&lt;/strong&gt; finds where to go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISP + IXP + BGP&lt;/strong&gt; decide &lt;em&gt;how&lt;/em&gt; to get there&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Servers/CDNs&lt;/strong&gt; deliver &lt;em&gt;what&lt;/em&gt; you asked for&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>basic</category>
      <category>backend</category>
    </item>
    <item>
      <title>Graphemes in Go</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Sun, 10 Aug 2025 03:40:00 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/graphemes-in-go-1n12</link>
      <guid>https://dev.to/ashwingopalsamy/graphemes-in-go-1n12</guid>
      <description>&lt;p&gt;I once ran into this problem of differentiating runes, bytes and graphemes while handling names in Tamil and emoji in a Go web app: a string that looked short wasn’t, and reversing it produced gibberish. The culprit wasn’t Go being flawed, it was me making assumptions about what “a character” means.&lt;/p&gt;

&lt;p&gt;Let’s map the territory precisely:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Bytes. The raw material Go calls a string
&lt;/h3&gt;

&lt;p&gt;Go represents strings as immutable UTF-8 byte sequences.&lt;/p&gt;

&lt;p&gt;What we &lt;em&gt;see&lt;/em&gt; isn’t what Go handles under the hood.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"வணக்கம்"&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// 21&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The length is 21 bytes not visible symbols. Every Tamil character can span 3 bytes. Even simple-looking emojis stretch across multiple bytes.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Runes. Unicode code points
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;string&lt;/code&gt; → &lt;code&gt;[]rune&lt;/code&gt;( gives you code points, but still not what a human perceives.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here it’s 7 runes, but some Tamil graphemes (like “க்”) combine two runes: &lt;code&gt;க&lt;/code&gt; + &lt;code&gt;்&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Grapheme clusters   the units users actually see
&lt;/h3&gt;

&lt;p&gt;Go’s standard library stops at runes. To work with visible characters, you need a grapheme-aware library, like &lt;code&gt;github.com/rivo/uniseg&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uniseg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewGraphemes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%q&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That outputs what a human reads “வ”, “ண”, “க்”, “க”, “ம்”, and even “❤️” as a single unit.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why this matters
&lt;/h3&gt;

&lt;p&gt;If your app deals with names, chats, or any multilingual text indexing by bytes will break things. Counting runes helps, but can still split what you intend as one unit. Grapheme-aware operations align with what users actually expect.&lt;/p&gt;

&lt;p&gt;Real bugs I’ve seen: Tamil names chopped mid-character, emoji reactions breaking because only one code point was taken.&lt;/p&gt;




&lt;h3&gt;
  
  
  To put it simply
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Count code points&lt;/td&gt;
&lt;td&gt;&lt;code&gt;utf8.RuneCountInString(s)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Count visible units&lt;/td&gt;
&lt;td&gt;Grapheme iteration (&lt;code&gt;uniseg&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse text&lt;/td&gt;
&lt;td&gt;Parse into graphemes, reverse slice, join&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slice safely&lt;/td&gt;
&lt;td&gt;Only use &lt;code&gt;s[i:j]&lt;/code&gt; on grapheme boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Think about what you intend to manipulate: the raw bytes, the code points, or what a user actually reads on screen and choose the right level.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Fri, 13 Dec 2024 15:10:12 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/-2mb4</link>
      <guid>https://dev.to/ashwingopalsamy/-2mb4</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/ashwingopalsamy" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1920945%2F83ec5409-92f8-41cc-b80e-86e5e510d9d5.jpg" alt="ashwingopalsamy"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/ashwingopalsamy/a-peek-behind-gos-entry-point-from-initialization-to-exit-3h9d" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A Peek Behind Go’s Entry Point - From Initialization to Exit&lt;/h2&gt;
      &lt;h3&gt;Ashwin Gopalsamy ・ Dec 13 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#go&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>A Peek Behind Go’s Entry Point - From Initialization to Exit</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Fri, 13 Dec 2024 15:10:02 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/a-peek-behind-gos-entry-point-from-initialization-to-exit-3h9d</link>
      <guid>https://dev.to/ashwingopalsamy/a-peek-behind-gos-entry-point-from-initialization-to-exit-3h9d</guid>
      <description>&lt;p&gt;When we first start with Go, the &lt;code&gt;main&lt;/code&gt; function seems almost too simple. A single entry point, a straightforward &lt;code&gt;go run main.go&lt;/code&gt; and voila - our program isup and running. &lt;/p&gt;

&lt;p&gt;But as we dug deeper, I realized there’s a subtle, well-thought-out process churning behind the curtain. Before main even begins, the Go runtime orchestrates a careful initialization of all imported packages, runs their init functions and ensures that everything’s in the right order - no messy surprises allowed.&lt;/p&gt;

&lt;p&gt;The way Go arranges has neat details to it, that I think every Go developer should be aware of, as this influences how we structure our code, handle shared resources and even communicate errors back to the system. &lt;/p&gt;

&lt;p&gt;Let’s explore some common scenarios and questions that highlight what’s really going on before and after main kicks into gear.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before main: Orderly Initialization and the Role of init
&lt;/h2&gt;

&lt;p&gt;Picture this: you’ve got multiple packages, each with their own init functions. Maybe one of them configures a database connection, another sets up some logging defaults and a third initializes a lambda worker &amp;amp; the fourth initializing an SQS queue listener. &lt;/p&gt;

&lt;p&gt;By the time main runs, you want everything ready - no half-initialized states or last-minute surprises.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Multiple Packages and &lt;code&gt;init&lt;/code&gt; Order&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// db.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db: connecting to the database..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// Imagine a real connection here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// cache.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cache: warming up the cache..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// Imagine setting up a cache here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// main.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"app/db"&lt;/span&gt;   &lt;span class="c"&gt;// blank import for side effects&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"app/cache"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"main: starting main logic now!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this program, you’ll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;db: connecting to the database...
cache: warming up the cache...
main: starting main logic now!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database initializes first (since &lt;code&gt;main&lt;/code&gt;imports &lt;code&gt;db&lt;/code&gt;), then the cache and finally main prints its message. Go guarantees that all imported packages are initialized before &lt;code&gt;main&lt;/code&gt;runs. This dependency-driven order is key. If &lt;code&gt;cache&lt;/code&gt; depended on &lt;code&gt;db&lt;/code&gt;, you’d be sure &lt;code&gt;db&lt;/code&gt; finished its setup before &lt;code&gt;cache&lt;/code&gt;’s &lt;code&gt;init&lt;/code&gt; ran.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ensuring a Specific Initialization Order
&lt;/h3&gt;

&lt;p&gt;Now, what if you absolutely need &lt;code&gt;db&lt;/code&gt;initialized before &lt;code&gt;cache&lt;/code&gt;, or vice versa? The natural approach is to ensure cache depends on &lt;code&gt;db&lt;/code&gt; or is imported after &lt;code&gt;db&lt;/code&gt; in &lt;code&gt;main&lt;/code&gt;. Go initializes packages in the order of their dependencies, not the order of imports listed in &lt;code&gt;main.go&lt;/code&gt;. A trick that we use is a blank import: &lt;code&gt;_ "path/to/package"&lt;/code&gt; - to force initialization of a particular package. But I wouldn’t rely on blank imports as a primary method; it can make dependencies less clear and lead to maintenance headaches.&lt;/p&gt;

&lt;p&gt;Instead, consider structuring packages so their initialization order emerges naturally from their dependencies. If that’s not possible, &lt;strong&gt;maybe the initialization logic shouldn’t rely on strict sequencing at compile time&lt;/strong&gt;. You could, for instance, have cache check if &lt;code&gt;db&lt;/code&gt; is ready at runtime, using a &lt;code&gt;sync.Once&lt;/code&gt; or a similar pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoiding Circular Dependencies
&lt;/h3&gt;

&lt;p&gt;Circular dependencies at the initialization level are a big no-no in Go. If package &lt;strong&gt;A&lt;/strong&gt; imports &lt;strong&gt;B&lt;/strong&gt; and &lt;strong&gt;B&lt;/strong&gt; tries to import &lt;strong&gt;A&lt;/strong&gt;, you’ve just created a &lt;em&gt;circular dependency&lt;/em&gt;. Go will refuse to compile, saving you from a world of confusing runtime issues. This might feel strict, but trust me, it’s better to find these problems early rather than debugging weird initialization states at runtime.&lt;/p&gt;




&lt;h3&gt;
  
  
  Dealing with Shared Resources and sync.Once
&lt;/h3&gt;

&lt;p&gt;Imagine a scenario where packages &lt;strong&gt;A&lt;/strong&gt; and &lt;strong&gt;B&lt;/strong&gt; both depend on a shared resource - maybe a configuration file or a global settings object. Both have &lt;code&gt;init&lt;/code&gt;functions and both try to initialize that resource. How do you ensure the resource is only initialized once?&lt;/p&gt;

&lt;p&gt;A common solution is to place the shared resource initialization behind a &lt;code&gt;sync.Once&lt;/code&gt; call. This ensures that the initialization code runs exactly one time, even if multiple packages trigger it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Ensuring Single Initialization&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// config.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;once&lt;/span&gt;      &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Once&lt;/span&gt;
    &lt;span class="n"&gt;someValue&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;once&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config: initializing shared resource..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;someValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"initialized"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;someValue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, no matter how many packages import &lt;code&gt;config&lt;/code&gt;, the initialization of &lt;code&gt;someValue&lt;/code&gt;happens only once. If package A and B both rely on &lt;code&gt;config.Value()&lt;/code&gt;, they’ll both see a properly initialized value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple init Functions in a Single File or Package
&lt;/h3&gt;

&lt;p&gt;You can have multiple &lt;code&gt;init&lt;/code&gt; functions in the same file and they’ll run in the order they appear. Across multiple files in the same package, Go runs &lt;code&gt;init&lt;/code&gt; functions in a consistent, but not strictly defined order. The compiler might process files in alphabetical order, but you shouldn’t rely on that. If your code depends on a specific sequence of &lt;code&gt;init&lt;/code&gt; functions within the same package, that’s often a sign to refactor. Keep &lt;code&gt;init&lt;/code&gt; logic minimal and avoid tight coupling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Legitimate Uses vs. Anti-Patterns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;init&lt;/code&gt; functions are best used for simple setup: registering database drivers, initializing command-line flags or setting up a logger. Complex logic, long-running I/O or code that might panic without good reason are better handled elsewhere. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a rule of thumb, if you find yourself writing a lot of logic in init, you might consider making that logic explicit in main.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Exiting with Grace and Understanding os.Exit()
&lt;/h3&gt;

&lt;p&gt;Go’s main doesn’t return a value. If you want to signal an error to the outside world, &lt;code&gt;os.Exit()&lt;/code&gt; is your friend. But keep in mind: calling &lt;code&gt;os.Exit()&lt;/code&gt; terminates the program immediately. No deferred functions run, no panic stack traces print.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Cleanup Before Exit&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;doSomethingRisky&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error occurred, performing cleanup..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;       &lt;span class="c"&gt;// Make sure to clean up before calling os.Exit&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Everything went fine!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;doSomethingRisky&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Pretend something failed&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something bad happened"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Close files, databases, flush buffers, etc.&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cleanup done!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you skip the cleanup call and jump straight to &lt;code&gt;os.Exit(1)&lt;/code&gt;, you lose the chance to clean up resources gracefully.&lt;/p&gt;

&lt;h4&gt;
  
  
  Other Ways to End a Program
&lt;/h4&gt;

&lt;p&gt;You can also end a program through a panic. A &lt;code&gt;panic&lt;/code&gt; that’s not recovered by &lt;code&gt;recover()&lt;/code&gt; in a deferred function will crash the program and print a stack trace. This is handy for debugging but not ideal for normal error signaling. Unlike &lt;code&gt;os.Exit()&lt;/code&gt;, a &lt;code&gt;panic&lt;/code&gt; gives deferred functions a chance to run before the program ends, which can help with cleanup, but it also might look less tidy to end-users or scripts expecting a clean exit code.&lt;/p&gt;

&lt;p&gt;Signals (like &lt;code&gt;SIGINT&lt;/code&gt; from &lt;code&gt;Cmd+C&lt;/code&gt;) can also terminate the program. If you’re a soldier, you can catch signals and handle them gracefully.&lt;/p&gt;




&lt;h3&gt;
  
  
  Runtime, Concurrency and the main Goroutine
&lt;/h3&gt;

&lt;p&gt;Initialization happens before any goroutines are launched, ensuring no race conditions at startup. Once &lt;code&gt;main&lt;/code&gt; begins, however, you can spin up as many goroutines as you like.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s important to note that main function in itself runs in a special “main goroutine” started by the Go runtime. If main returns, the entire program exits - even if other goroutines are still doing work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a common gotcha: just because you started background goroutines doesn’t mean they keep the program alive. Once main finishes, everything shuts down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Goroutine finished its job!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="c"&gt;// If we simply return here, the main goroutine finishes,&lt;/span&gt;
    &lt;span class="c"&gt;// and the program exits immediately, never printing the above message.&lt;/span&gt;

    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main is done, exiting now!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the goroutine prints its message only because &lt;code&gt;main&lt;/code&gt; waits 3 seconds before ending. If &lt;code&gt;main&lt;/code&gt; ended sooner, the program would terminate before the goroutine completed. The runtime doesn’t “wait around” for other goroutines when &lt;code&gt;main&lt;/code&gt; exits. If your logic demands waiting for certain tasks to complete, consider using synchronization primitives like &lt;code&gt;WaitGroup&lt;/code&gt; or channels to signal when background work is done.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if a Panic Occurs During Initialization?
&lt;/h3&gt;

&lt;p&gt;If a panic happens during &lt;code&gt;init&lt;/code&gt;, the whole program terminates. No &lt;code&gt;main&lt;/code&gt;, no recovery opportunity. You’ll see a panic message that can help you debug. This is one reason why I try to keep my &lt;code&gt;init&lt;/code&gt; functions simple, predictable and free of complex logic that might blow up unexpectedly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wrapping It Up
&lt;/h3&gt;

&lt;p&gt;By the time &lt;code&gt;main&lt;/code&gt; runs, Go has already done a ton of invisible legwork: it’s initialized all your packages, run every &lt;code&gt;init&lt;/code&gt; function and checked that there are no nasty circular dependencies lurking around. Understanding this process gives you more control and confidence in your application’s startup sequence.&lt;/p&gt;

&lt;p&gt;When something goes wrong, you know how to exit cleanly and what happens to deferred functions. When your code grows more complex, you know how to enforce initialization order without resorting to hacks. And if concurrency comes into play, you know that the race conditions start after init runs, not before.&lt;/p&gt;

&lt;p&gt;For me, these insights made Go’s seemingly simple main function feel like the tip of an elegant iceberg. If you have your own tricks, pitfalls you’ve stumbled into, or questions about these internals, I’d love to hear them. &lt;/p&gt;

&lt;p&gt;After all, we’re all still learning - and that’s half the fun of being a Go developer.&lt;/p&gt;




&lt;p&gt;Thanks for reading! May the code be with you :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Social Links:&lt;/strong&gt; &lt;a href="https://linkedin.com/in/ashwingopalsamy" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="http://github.com/ashwingopalsamy" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;| &lt;a href="http://x.com/ashwin2125" rel="noopener noreferrer"&gt;𝕏 (formerly Twitter)&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.substack.com/" rel="noopener noreferrer"&gt;Substack &lt;/a&gt;| &lt;a href="https://dev.to/ashwingopalsamy"&gt;Dev.to&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more content, please consider following. See ya!&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Fri, 06 Dec 2024 16:40:25 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/-4b5i</link>
      <guid>https://dev.to/ashwingopalsamy/-4b5i</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/ashwingopalsamy" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1920945%2F83ec5409-92f8-41cc-b80e-86e5e510d9d5.jpg" alt="ashwingopalsamy"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/ashwingopalsamy/a-tiny-dependency-free-uuid-checker-for-go-18oe" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;A Tiny, Dependency-Free UUID Checker for Go!&lt;/h2&gt;
      &lt;h3&gt;Ashwin Gopalsamy ・ Dec 6 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#go&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#uuid&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>A Tiny, Dependency-Free UUID Checker for Go!</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Fri, 06 Dec 2024 16:40:07 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/a-tiny-dependency-free-uuid-checker-for-go-18oe</link>
      <guid>https://dev.to/ashwingopalsamy/a-tiny-dependency-free-uuid-checker-for-go-18oe</guid>
      <description>&lt;p&gt;As like few folks, at times, when I deal with UUIDs in Go, I rarely needed a big, feature-packed library - just a lean way to confirm something basic, like, “&lt;em&gt;Yes, that string is definitely a UUID.&lt;/em&gt;” Sometimes, I’d also want to check if it was a UUIDv7 and maybe peek at its embedded ‘&lt;em&gt;timestamp&lt;/em&gt;’.&lt;/p&gt;

&lt;p&gt;Nothing major, just a quiet helper in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  And what?
&lt;/h2&gt;

&lt;p&gt;That’s why I built uuidcheck. It’s not a complex stuff, just a handful of meaningful functions that stick to Go’s standard library. No external dependencies at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Only the baby steps?
&lt;/h2&gt;

&lt;p&gt;I didn’t stop at making it small. I wrote clear Go-doc style documentation so you can read about each function right in pkg.go.dev; no guesswork needed. Every corner of the logic got a unit test, pushing coverage to 100%. It wasn’t hard, given the library’s size, but it’s nice to know everything’s solid. If a weird edge case comes up, I can trust the tests already have my back. Even if something slipped my mind, I would love your ‘good first contribution’ to the library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you need to care?
&lt;/h2&gt;

&lt;p&gt;To be honest, most projects don’t need a daily UUID validation routine or a quick timestamp extraction from UUIDv7 strings. But when you do, uuidcheck might save you from writing the same checks over and over. It’s small, neat, and does the job without weighing you down.&lt;/p&gt;

&lt;p&gt;So, if you ever find yourself thinking, “I just need to confirm this is a real UUID, nothing else.” Remember &lt;a href="//github.com/ashwingopalsamy/uuidcheck"&gt;github.com/ashwingopalsamy/uuidcheck&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s there to help, staying out of your way, and giving you that tiny bit of confidence where it matters.&lt;/p&gt;

&lt;p&gt;Thanks for reading! May the code be with you :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Social Links:&lt;/strong&gt; &lt;a href="https://linkedin.com/in/ashwingopalsamy" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="http://github.com/ashwingopalsamy" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;| &lt;a href="http://x.com/ashwin2125" rel="noopener noreferrer"&gt;𝕏 (formerly Twitter)&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.substack.com/" rel="noopener noreferrer"&gt;Substack &lt;/a&gt;| &lt;a href="https://dev.to/ashwingopalsamy"&gt;Dev.to&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more content, please consider subscribing. See ya!&lt;/p&gt;

</description>
      <category>go</category>
      <category>uuid</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Git -&gt; GitHub -&gt; GPG Key (Windows)</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Sun, 01 Dec 2024 13:26:04 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/git-github-gpg-key-windows-2016</link>
      <guid>https://dev.to/ashwingopalsamy/git-github-gpg-key-windows-2016</guid>
      <description>&lt;p&gt;If you're a beginner to Git or just starting to tinker with GitHub and GPG, you're probably here because you want to get that super-cute green "&lt;em&gt;Verified&lt;/em&gt;" label next to your commits. The one that makes your contributions look professional and trusted. But, like most of us, you might have run into a few snags while setting up GPG keys on &lt;strong&gt;Windows&lt;/strong&gt;. Don’t worry—you're not alone!&lt;/p&gt;

&lt;p&gt;In this guide, I'll walk you through the entire process of setting up GPG for signing your GitHub commits on Windows. Plus, I’ll show you how I fixed a few tricky issues along the way. So, grab your coffee, and let's dive into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Git Bash
&lt;/h3&gt;

&lt;p&gt;Before we get into the GPG configuration, let's talk about Git Bash. &lt;strong&gt;Git Bash&lt;/strong&gt; is a terminal emulator that comes with Git for Windows. If you haven’t installed it yet, do yourself a favor and install it. You can get it from the &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;official Git website&lt;/a&gt;. Git Bash is much more user-friendly for these kinds of setups, and it plays better with Unix-based commands that you’ll need for GPG (like &lt;code&gt;export&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Using Git Bash throughout this process will save you from some headaches, especially when working with environment variables. Trust me, you’ll thank me later.&lt;/p&gt;

&lt;p&gt;Once you've installed Git Bash, open it up. Now, you're ready to go!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Install GPG4Win (and GPG)
&lt;/h3&gt;

&lt;p&gt;To get started with GPG, you’ll need to install &lt;strong&gt;GPG4Win&lt;/strong&gt;, which is the suite that includes everything you need to generate your keys. You can download it from &lt;a href="https://gpg4win.org/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After installation, make sure GPG is accessible by running the following command in Git Bash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should return the version number of GPG if it’s properly installed. If you get an error, go back to the installation and make sure it went smoothly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Generate a GPG Key
&lt;/h3&gt;

&lt;p&gt;Next, let’s generate your GPG key. This is the key that will be used to sign your Git commits.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the following command in Git Bash to create your GPG key:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpg &lt;span class="nt"&gt;--full-generate-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Choose the default options (RSA and RSA, key size 4096, etc.), and when asked for your name and email, use the &lt;strong&gt;same email&lt;/strong&gt; that you have registered with GitHub.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Real name: Your Name
   Email address: your-email@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Make sure the email you enter matches the one on your GitHub account. If it doesn't, GitHub won’t be able to associate your commits with your account.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once the key is generated, list your keys to find the key ID:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpg &lt;span class="nt"&gt;--list-secret-keys&lt;/span&gt; &lt;span class="nt"&gt;--keyid-format&lt;/span&gt; LONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will output a long string with your key ID. It should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   sec   rsa4096/XXXXXXXXXXXXXXXX 2024-12-01 [SC] [expires: 2027-12-01]
         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   uid                 [ultimate] Your Name &amp;lt;your-email@example.com&amp;gt;
   ssb   rsa4096/XXXXXXXXXXXXXXXX 2024-12-01 [E] [expires: 2027-12-01]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy your key ID from the &lt;code&gt;rsa4096/XXXXXXXXXXXXXXXX&lt;/code&gt; part. You'll need it for later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Add Your GPG Key to Git
&lt;/h3&gt;

&lt;p&gt;Now that your GPG key is ready, let's tell Git to use it for signing commits. First, export the public key to add it to GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--armor&lt;/span&gt; &lt;span class="nt"&gt;--export&lt;/span&gt; your-email@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will print your public GPG key in ASCII format. Copy the entire output (starting with &lt;code&gt;-----BEGIN PGP PUBLIC KEY BLOCK-----&lt;/code&gt; and ending with &lt;code&gt;-----END PGP PUBLIC KEY BLOCK-----&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Next, add this key to GitHub:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your GitHub account and navigate to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;SSH and GPG Keys&lt;/strong&gt; &amp;gt; &lt;strong&gt;New GPG Key&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Paste your public key into the box and save it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 5: Configure Git to Use Your GPG Key
&lt;/h3&gt;

&lt;p&gt;Let’s tell Git to use your GPG key when signing commits. Run the following command in Git Bash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.signingkey your-key-id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;your-key-id&lt;/code&gt; with the GPG key ID you copied earlier.&lt;/p&gt;

&lt;p&gt;Then, configure Git to automatically sign your commits by default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; commit.gpgSign &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that every commit you make will be signed automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Test Your Setup
&lt;/h3&gt;

&lt;p&gt;You’re almost there! Now, let’s test if everything is working properly. Try making a commit in any of your repositories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make a small change to a file and commit it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Test commit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Push the commit to GitHub:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Check GitHub. If everything is set up correctly, you should now see the &lt;strong&gt;"Verified"&lt;/strong&gt; label next to your commit on GitHub!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Common Issues &amp;amp; Fixes
&lt;/h3&gt;

&lt;p&gt;Okay, so you followed all the steps, but you’re still facing some issues? I’ve been there, and I’ve got you covered with a couple of extra fixes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Problem 1: "No 'Verified' label?" – Even After Everything Looks Fine
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The Issue&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
If you’re getting the GPG key to work locally but don’t see the "Verified" label on GitHub, there’s a chance the problem lies in how you're using the terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
In Windows, &lt;strong&gt;PowerShell&lt;/strong&gt; can be tricky when it comes to handling environment variables like &lt;code&gt;GPG_TTY&lt;/code&gt;, which is necessary for GPG to function properly. The solution is to either set the environment variable correctly in PowerShell or switch to Git Bash.&lt;/p&gt;

&lt;p&gt;Here’s what worked for me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In PowerShell&lt;/strong&gt;, set the &lt;code&gt;GPG_TTY&lt;/code&gt; environment variable with this command:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;GPG_TTY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"COM1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Alternatively, you can point directly to the &lt;code&gt;gpg.exe&lt;/code&gt; executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;GPG_TTY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:/Program Files (x86)/GnuPG/bin/gpg.exe"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Switch to Git Bash&lt;/strong&gt; (if you're still facing issues). Git Bash works more naturally with Unix-style commands, including setting environment variables with &lt;code&gt;export&lt;/code&gt;. In Git Bash, run:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GPG_TTY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;tty&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should resolve most issues with signing commits in Git.&lt;/p&gt;

&lt;h4&gt;
  
  
  Problem 2: GPG Errors on Windows – "No Secret Key"
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The Issue&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
This error usually means Git can’t find your GPG private key for signing commits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check where GPG is installed&lt;/strong&gt; using:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   where gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This should show you the path to your &lt;code&gt;gpg.exe&lt;/code&gt;. Make sure it's pointing to the correct version, usually located in &lt;code&gt;C:\Program Files (x86)\GnuPG\bin\gpg.exe&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configure Git to use the correct GPG version&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If Git is pointing to the wrong GPG version, set it explicitly with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git config &lt;span class="nt"&gt;--global&lt;/span&gt; gpg.program &lt;span class="s2"&gt;"C:/Program Files (x86)/GnuPG/bin/gpg.exe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Double-check your GPG key&lt;/strong&gt; with:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpg &lt;span class="nt"&gt;--list-secret-keys&lt;/span&gt; &lt;span class="nt"&gt;--keyid-format&lt;/span&gt; LONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure your key appears. If it doesn’t, you’ll need to import it into your keyring.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;Setting up GPG on Windows for GitHub commit signing can be a bit tricky, but once you’ve got everything in place, it’s totally worth it to see that “Verified” label next to your commits.&lt;/p&gt;

&lt;p&gt;Just remember to use Git Bash to avoid some of the headaches with PowerShell and to set the correct environment variables. If you're running into GPG errors or issues with secret keys, double-check your paths and keys, and you should be good to go!&lt;/p&gt;

&lt;p&gt;Happy coding, and enjoy the satisfaction of seeing your verified commits on GitHub! If you have any other issues or tips to share, drop a comment or tweet at me. Let's make this process smoother for everyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Social Links:&lt;/strong&gt; &lt;a href="https://linkedin.com/in/ashwingopalsamy" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="http://github.com/ashwingopalsamy" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;| &lt;a href="http://x.com/ashwin2125" rel="noopener noreferrer"&gt;𝕏 (formerly Twitter)&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.substack.com/" rel="noopener noreferrer"&gt;Substack &lt;/a&gt;| &lt;a href="https://dev.to/ashwingopalsamy"&gt;Dev.to&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>microsoft</category>
      <category>gpg</category>
    </item>
    <item>
      <title>Git: Set Up Commit Signing with GPG on Mac ✅</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Tue, 19 Nov 2024 06:28:53 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/struggling-with-git-commit-signing-heres-what-fixed-it-for-me-a7e</link>
      <guid>https://dev.to/ashwingopalsamy/struggling-with-git-commit-signing-heres-what-fixed-it-for-me-a7e</guid>
      <description>&lt;p&gt;If you've ever tried setting up commit signing with GPG on GitHub and ended up scratching your head, especially on Mac? You're not alone.&lt;/p&gt;

&lt;p&gt;You follow the official docs, generate a key, link it to GitHub, and set it up in your local repo, but your commits still show as "Unverified." That’s exactly what happened to me, and here’s how I finally got it working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating Your GPG Key
&lt;/h2&gt;

&lt;p&gt;The first step is generating the GPG key, which is usually pretty straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generate the key&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpg &lt;span class="nt"&gt;--full-generate-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Find your key ID&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpg &lt;span class="nt"&gt;--list-secret-keys&lt;/span&gt; &lt;span class="nt"&gt;--keyid-format&lt;/span&gt; LONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Export the key&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpg &lt;span class="nt"&gt;--armor&lt;/span&gt; &lt;span class="nt"&gt;--export&lt;/span&gt; YOUR_KEY_ID &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; my-gpg-key.asc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add the key to GitHub&lt;/strong&gt;: Copy the output from the previous command and go to &lt;strong&gt;GitHub Settings &amp;gt; SSH and GPG keys &amp;gt; New GPG key&lt;/strong&gt;. Paste it in there.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once this is done, tell Git to use this key for signing commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.signingkey YOUR_KEY_ID
git config &lt;span class="nt"&gt;--global&lt;/span&gt; commit.gpgSign &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should take care of the basics. At this point, every commit you make should be signed with your GPG key.&lt;/p&gt;

&lt;h2&gt;
  
  
  But Is It Working? Check Your Repo’s Config
&lt;/h2&gt;

&lt;p&gt;I thought I was all set until I started seeing "unverified" commits again. Here’s the thing: While you may have set the global config for commit signing, each repository has its own individual config. So, even if your global settings are correct, you still need to check the specific repo configuration.&lt;/p&gt;

&lt;p&gt;Run the following to check if commit signing is enabled for your current repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config commit.gpgSign
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If the output is &lt;code&gt;true&lt;/code&gt;, you're good to go.&lt;/li&gt;
&lt;li&gt;If it’s &lt;code&gt;false&lt;/code&gt; (or if there’s no output), you need to enable it with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config commit.gpgSign &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s a small step, but if it's not set, Git won’t sign your commits in that repo, even if you’ve got everything else configured correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t Want to Type Your Passphrase Everytime? Cache It!
&lt;/h2&gt;

&lt;p&gt;If you’re signing commits frequently, typing your GPG passphrase every single time can get old. The good news is, you can cache the passphrase for a certain period, so you don’t have to re-enter it every time you make a commit.&lt;/p&gt;

&lt;p&gt;To do this, add these lines to your &lt;code&gt;~/.gnupg/gpg-agent.conf&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;default-cache-ttl 600
max-cache-ttl 7200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will cache your passphrase for 10 minutes, and the maximum cache time will be 2 hours. After that, GPG will ask you for your passphrase again.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPG Not Working? Try Restarting the GPG Agent
&lt;/h2&gt;

&lt;p&gt;Sometimes things can just break for no reason. You might notice that keys stop working, commits aren’t signed, or you see weird errors. When this happens, one thing that tends to help is restarting the GPG agent.&lt;/p&gt;

&lt;p&gt;You can do that with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpgconf &lt;span class="nt"&gt;--kill&lt;/span&gt; gpg-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command forces the GPG agent to restart the next time you use it. It’s a simple fix but can clear up a lot of problems when things go sideways.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Desktop Issues: No Passphrase Prompt or "Signing Failed"
&lt;/h2&gt;

&lt;p&gt;If you’re using &lt;strong&gt;GitHub Desktop&lt;/strong&gt; and facing issues with GPG signing (like not getting a passphrase prompt, or encountering the error &lt;code&gt;gpg: signing failed: No such file or directory&lt;/code&gt;), the issue might be related to how GitHub Desktop interacts with GPG.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;GitHub Desktop may not properly launch the passphrase entry dialog for your GPG key, or it might not find the GPG agent. This can result in errors like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg: signing failed: No such file or directory
fatal: failed to write commit object
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install &lt;code&gt;pinentry-mac&lt;/code&gt;&lt;/strong&gt;:
GitHub Desktop often requires the &lt;code&gt;pinentry-mac&lt;/code&gt; program for handling the passphrase prompt. Install it using Homebrew:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   brew &lt;span class="nb"&gt;install &lt;/span&gt;pinentry-mac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configure GPG to Use &lt;code&gt;pinentry-mac&lt;/code&gt;&lt;/strong&gt;:
Next, make sure GPG uses the right pinentry program by adding this line to your &lt;code&gt;~/.gnupg/gpg-agent.conf&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"pinentry-program &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;which pinentry-mac&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gnupg/gpg-agent.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Restart the GPG Agent&lt;/strong&gt;:
After updating the configuration, restart the GPG agent to apply the changes:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpgconf &lt;span class="nt"&gt;--kill&lt;/span&gt; gpg-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check GPG Version&lt;/strong&gt;:
Ensure you're using GPG version 2+, as older versions don’t support modern features like &lt;code&gt;pinentry-mode loopback&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gpg &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have an older version, update GPG with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   brew &lt;span class="nb"&gt;install &lt;/span&gt;gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you’ve done this, try again in GitHub Desktop. You should now be prompted for your passphrase, and commits will be signed correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You’re Still Stuck
&lt;/h3&gt;

&lt;p&gt;If you continue to encounter issues, you might want to try signing a commit directly from the terminal to isolate whether the issue is with GitHub Desktop or your GPG setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;--no-edit&lt;/span&gt; &lt;span class="nt"&gt;--gpg-sign&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this works but GitHub Desktop still doesn’t, the issue is likely specific to GitHub Desktop's interaction with GPG.&lt;/p&gt;

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

&lt;p&gt;Getting GPG commit signing set up on GitHub can be a bit of a pain, especially when things don’t work as expected. But once it’s up and running, it’s a great way to ensure the authenticity of your commits. Here’s a quick checklist to make sure everything’s working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check your repo’s &lt;code&gt;commit.gpgSign&lt;/code&gt; config&lt;/strong&gt;: Make sure it’s set to &lt;code&gt;true&lt;/code&gt; for your repo with &lt;code&gt;git config commit.gpgSign&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache your passphrase&lt;/strong&gt;: Use &lt;code&gt;gpg-agent&lt;/code&gt; to avoid entering your passphrase every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restart the GPG agent&lt;/strong&gt;: If things go wrong, use &lt;code&gt;gpgconf --kill gpg-agent&lt;/code&gt; to reset your keys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For GitHub Desktop users&lt;/strong&gt;: Install &lt;code&gt;pinentry-mac&lt;/code&gt; and configure GPG to use it to resolve issues with the passphrase prompt and signing failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re still running into issues, or if you’ve got a better way of managing GPG with GitHub, leave a comment. I’d love to hear your thoughts!&lt;/p&gt;

&lt;p&gt;Thanks for reading. May the code be with you!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Social Links:&lt;/strong&gt; &lt;a href="https://linkedin.com/in/ashwingopalsamy" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="http://github.com/ashwingopalsamy" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;| &lt;a href="http://x.com/ashwin2125" rel="noopener noreferrer"&gt;𝕏 (formerly Twitter)&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.substack.com/" rel="noopener noreferrer"&gt;Substack &lt;/a&gt;| &lt;a href="https://dev.to/ashwingopalsamy"&gt;Dev.to&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>gpg</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Go: Pointers &amp; Memory Management</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Sun, 17 Nov 2024 11:54:41 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/go-pointers-memory-management-3ole</link>
      <guid>https://dev.to/ashwingopalsamy/go-pointers-memory-management-3ole</guid>
      <description>&lt;p&gt;TL;DR: Explore Go’s memory handling with pointers, stack and heap allocations, escape analysis and garbage collection with examples&lt;/p&gt;

&lt;p&gt;When I first started learning Go, I was intrigued by its approach to memory management, especially when it came to pointers. Go handles memory in a way that's both efficient and safe, but it can be a bit of a black box if you don't peek under the hood. I want to share some insights into how Go manages memory with pointers, the stack and heap, and concepts like escape analysis and garbage collection. Along the way, we'll look at code examples that illustrate these ideas in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Stack and Heap Memory
&lt;/h2&gt;

&lt;p&gt;Before diving into pointers in Go, it's helpful to understand how the stack and heap work. These are two areas of memory where variables can be stored, each with its own characteristics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stack&lt;/strong&gt;: This is a region of memory that operates in a last-in, first-out manner. It's fast and efficient, used for storing variables with short-lived scope, like local variables within functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heap&lt;/strong&gt;: This is a larger pool of memory used for variables that need to live beyond the scope of a function, such as data that's returned from a function and used elsewhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Go, the compiler decides whether to allocate variables on the stack or the heap based on how they're used. This decision-making process is called &lt;strong&gt;escape analysis&lt;/strong&gt;, which we'll explore in more detail later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing by Value: The Default Behavior
&lt;/h2&gt;

&lt;p&gt;In Go, when you pass variables like integer, string, or boolean to a function, they are naturally passed by value. This means a copy of the variable is made, and the function works with that copy. This means, any change made to the variable inside the function will not affect the variable outside its scope.&lt;/p&gt;

&lt;p&gt;Here's &lt;a href="https://go.dev/play/p/P7b0Uu9cd8n" rel="noopener noreferrer"&gt;a simple example&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Inside increment(): num = %d, address = %p &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Before increment(): n = %d, address = %p &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"After increment(): n = %d, address = %p &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before increment(): n = 21, address = 0xc000012070 
Inside increment(): num = 22, address = 0xc000012078 
After increment(): n = 21, address = 0xc000012070
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;increment()&lt;/code&gt; function receives a copy of &lt;code&gt;n&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The addresses of &lt;code&gt;n&lt;/code&gt; in &lt;code&gt;main()&lt;/code&gt; and &lt;code&gt;num&lt;/code&gt; in &lt;code&gt;increment()&lt;/code&gt; are different.&lt;/li&gt;
&lt;li&gt;Modifying &lt;code&gt;num&lt;/code&gt; inside &lt;code&gt;increment()&lt;/code&gt; doesn't affect &lt;code&gt;n&lt;/code&gt; in &lt;code&gt;main()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: Passing by value is safe and straightforward, but for large data structures, copying may become inefficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Pointers: Passing by Reference
&lt;/h2&gt;

&lt;p&gt;To modify the original variable inside a function, you can pass a pointer to it. A pointer holds the memory address of a variable, allowing functions to access and modify the original data.&lt;/p&gt;

&lt;p&gt;Here's &lt;a href="https://go.dev/play/p/QeTd1jt9qKK" rel="noopener noreferrer"&gt;how you can use pointers&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;incrementPointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Inside incrementPointer(): num = %d, address = %p &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Before incrementPointer(): n = %d, address = %p &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;incrementPointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"After incrementPointer(): n = %d, address = %p &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before incrementPointer(): n = 42, address = 0xc00009a040 
Inside incrementPointer(): num = 43, address = 0xc00009a040 
After incrementPointer(): n = 43, address = 0xc00009a040 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We pass the address of &lt;code&gt;n&lt;/code&gt; to &lt;code&gt;incrementPointer()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Both &lt;code&gt;main()&lt;/code&gt; and &lt;code&gt;incrementPointer()&lt;/code&gt; refer to the same memory address.&lt;/li&gt;
&lt;li&gt;Modifying &lt;code&gt;num&lt;/code&gt; inside &lt;code&gt;incrementPointer()&lt;/code&gt; affects &lt;code&gt;n&lt;/code&gt; in &lt;code&gt;main()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: Using pointers allows functions to modify the original variable, but it introduces considerations about memory allocation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Allocation with Pointers
&lt;/h2&gt;

&lt;p&gt;When you create a pointer to a variable, Go needs to ensure that the variable lives as long as the pointer does. This often means allocating the variable on the &lt;strong&gt;&lt;em&gt;heap&lt;/em&gt;&lt;/strong&gt; rather than the &lt;strong&gt;&lt;em&gt;stack&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createPointer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;num&lt;/code&gt; is a local variable within &lt;code&gt;createPointer()&lt;/code&gt;. If &lt;code&gt;num&lt;/code&gt; were stored on the stack, it would be cleaned up once the function returns, leaving a dangling pointer. To prevent this, Go allocates &lt;code&gt;num&lt;/code&gt; on the heap so that it remains valid after &lt;code&gt;createPointer()&lt;/code&gt; exits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dangling Pointers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;dangling pointer&lt;/strong&gt; occurs when a pointer refers to memory that has already been freed. &lt;/p&gt;

&lt;p&gt;Go prevents dangling pointers with its garbage collector, ensuring that memory is not freed while it is still referenced. However, holding onto pointers longer than necessary can lead to increased memory usage or memory leaks in certain scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escape Analysis: Deciding Stack vs. Heap Allocation
&lt;/h2&gt;

&lt;p&gt;Escape analysis determines whether variables need to live beyond their function scope. If a variable is returned, stored in a pointer, or captured by a goroutine, it escapes and is allocated on the heap. However, even if a variable doesn’t escape, the compiler might allocate it on the heap for other reasons, such as optimization decisions or stack size limitations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of a Variable Escaping:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"nums: %v&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The slice &lt;code&gt;data&lt;/code&gt; in &lt;code&gt;createSlice()&lt;/code&gt; escapes because it's returned and used in &lt;code&gt;main()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The underlying array of the slice is allocated on the &lt;strong&gt;heap&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Understanding Escape Analysis with &lt;code&gt;go build -gcflags '-m'&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can see what Go's compiler decides by using the &lt;code&gt;-gcflags '-m'&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go build &lt;span class="nt"&gt;-gcflags&lt;/span&gt; &lt;span class="s1"&gt;'-m'&lt;/span&gt; main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will output messages indicating whether variables escape to the heap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Garbage Collection in Go
&lt;/h2&gt;

&lt;p&gt;Go uses a garbage collector to manage memory allocation and deallocation on the heap. It automatically frees memory that's no longer referenced, helping prevent memory leaks.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

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

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Next&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createLinkedList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;createLinkedList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Linked list created"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// The garbage collector will clean up when 'list' as it was not used&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We create a linked list with 1,000,000 nodes.&lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;Node&lt;/code&gt; is allocated on the heap because it escapes the scope of &lt;code&gt;createLinkedList()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The garbage collector frees the memory when the list is no longer needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: Go's garbage collector simplifies memory management but can introduce overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential Pitfalls with Pointers
&lt;/h2&gt;

&lt;p&gt;While pointers are powerful, they can lead to issues if not used carefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dangling Pointers (Continued)
&lt;/h3&gt;

&lt;p&gt;Although Go's garbage collector helps prevent dangling pointers, you can still run into problems if you hold onto pointers longer than necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://go.dev/play/p/rTrIddmIKyQ" rel="noopener noreferrer"&gt;Example&lt;/a&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;createData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data created"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data still in use:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c"&gt;// this pointer is not dereferenced yet&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt; is a large slice allocated on the heap.&lt;/li&gt;
&lt;li&gt;By keeping a reference to it (&lt;code&gt;[]int&lt;/code&gt;), we prevent the garbage collector from freeing the memory.&lt;/li&gt;
&lt;li&gt;This can lead to increased memory usage if not managed properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Concurrency Issues - Data Race with Pointers
&lt;/h3&gt;

&lt;p&gt;Here's an example where pointers are directly involved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;counterPtr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="c"&gt;// Pointer to the counter&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counterPtr&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c"&gt;// Dereference the pointer and increment&lt;/span&gt;
            &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Counter:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counterPtr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Code Fails:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple goroutines dereference and increment the pointer &lt;code&gt;counterPtr&lt;/code&gt; without any synchronization.&lt;/li&gt;
&lt;li&gt;This leads to a data race because multiple goroutines access and modify the same memory location concurrently without synchronization. The operation &lt;code&gt;*counterPtr++&lt;/code&gt; involves multiple steps (read, increment, write) and is not thread-safe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fixing the Data Race:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can fix this by adding synchronization with a mutex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;counterPtr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="c"&gt;// Pointer to the counter&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counterPtr&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c"&gt;// Safely dereference and increment&lt;/span&gt;
            &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Counter:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counterPtr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How This Fix Works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;mu.Lock()&lt;/code&gt; and &lt;code&gt;mu.Unlock()&lt;/code&gt; ensure that only one goroutine accesses and modifies the pointer at a time.&lt;/li&gt;
&lt;li&gt;This prevents race conditions and ensures the final value of &lt;code&gt;counter&lt;/code&gt; is correct.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What does Go's Language Specification say?
&lt;/h2&gt;

&lt;p&gt;It's worth noting that &lt;strong&gt;Go's language specification doesn't directly dictate whether variables are allocated on the stack or the heap&lt;/strong&gt;. These are runtime and compiler implementation details, allowing for flexibility and optimizations that can vary across Go versions or implementations.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The way memory is managed can change between different versions of Go.&lt;/li&gt;
&lt;li&gt;You shouldn't rely on variables being allocated in a specific area of memory.&lt;/li&gt;
&lt;li&gt;Focus on writing clear and correct code rather than trying to control memory allocation.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Even if you expect a variable to be allocated on the stack, the compiler might decide to move it to the heap based on its analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="c"&gt;// The compiler may choose to allocate 'data' on the heap&lt;/span&gt;
    &lt;span class="c"&gt;// if it deems it more efficient&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: As the memory allocation details are kinda internal implementation and not part of the Go Language Specification, these information are only general guidelines and not fixed rules which might change at a later date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Balancing Performance and Memory Usage
&lt;/h2&gt;

&lt;p&gt;When deciding between passing by value or by pointer, we must consider the size of the data and the performance implications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passing Large Structs by Value:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;LargeStruct&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;processValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt; &lt;span class="n"&gt;LargeStruct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Processing data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ls&lt;/span&gt; &lt;span class="n"&gt;LargeStruct&lt;/span&gt;
    &lt;span class="n"&gt;processValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Copies the entire struct&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Passing Large Structs by Pointer:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;processPointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;LargeStruct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Processing data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ls&lt;/span&gt; &lt;span class="n"&gt;LargeStruct&lt;/span&gt;
    &lt;span class="n"&gt;processPointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Passes a pointer, avoids copying&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Passing by value is safe and straightforward but can be inefficient for large data structures.&lt;/li&gt;
&lt;li&gt;Passing by pointer avoids copying but requires careful handling to avoid concurrency issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  From the field experience:
&lt;/h2&gt;

&lt;p&gt;In early career, a recall a time when I was optimizing a Go application that processed large sets of data. Initially, I passed large structs by value, assuming it would simplify reasoning about the code. However, I happened to notice comparably high memory usage and frequent garbage collection pauses.&lt;/p&gt;

&lt;p&gt;After profiling the application using Go's &lt;code&gt;pprof&lt;/code&gt; tool in a pair programming with my senior, we found that copying large structs was a bottleneck. We refactored the code to pass pointers instead of values. This reduced memory usage and improved performance significantly.&lt;/p&gt;

&lt;p&gt;But the change wasn't without challenges. We had to ensure that our code was thread-safe since multiple goroutines were now accessing shared data. We implemented synchronization using mutexes and carefully reviewed the code for potential race conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson Learned&lt;/strong&gt;: Very early understanding how Go handles memory allocation can help you write more efficient code, as it's essential to balance performance gains with code safety and maintainability.&lt;/p&gt;

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

&lt;p&gt;Go's approach to memory management (like how it does everywhere else) strikes a balance between performance and simplicity. By abstracting away many low-level details, it allows developers to focus on building robust applications without getting bogged down in manual memory management.&lt;/p&gt;

&lt;p&gt;Key points to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Passing by value&lt;/strong&gt; is simple but can be inefficient for large data structures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using pointers&lt;/strong&gt; can improve performance but requires careful handling to avoid issues like data races.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escape analysis&lt;/strong&gt; determines whether variables are allocated on the stack or heap, but this is an internal detail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage collection&lt;/strong&gt; helps prevent memory leaks but might introduce overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt; requires synchronization when shared data is involved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By keeping these concepts in mind and using Go's tools to profile and analyze your code, you can write efficient and safe applications.&lt;/p&gt;




&lt;p&gt;I hope this exploration of Go's memory management with pointers will be helpful. Whether you're just starting with Go or looking to deepen your understanding, experimenting with code and observing how the compiler and runtime behave is a great way to learn. &lt;/p&gt;

&lt;p&gt;Feel free to share your experiences or any questions you might have — I'm always keen to discuss, learn and write more about Go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus Content - Direct Pointer Support
&lt;/h2&gt;

&lt;p&gt;You know? Pointers can be directly created for certain datatypes and cannot, for some. This short table covers them.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Supports Direct Pointer Creation?&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Structs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;p := &amp;amp;Person{Name: "Alice", Age: 30}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Arrays&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;arrPtr := &amp;amp;[3]int{1, 2, 3}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Slices&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ No (indirect via variable)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;slice := []int{1, 2, 3}; slicePtr := &amp;amp;slice&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ No (indirect via variable)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m := map[string]int{}; mPtr := &amp;amp;m&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Channels&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ No (indirect via variable)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ch := make(chan int); chPtr := &amp;amp;ch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Basic Types&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ No (requires a variable)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;val := 42; p := &amp;amp;val&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;time.Time (Struct)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t := &amp;amp;time.Time{}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Structs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;point := &amp;amp;Point{X: 1, Y: 2}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interface Types&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes (but rarely needed)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var iface interface{} = "hello"; ifacePtr := &amp;amp;iface&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;time.Duration (Alias of int64)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;duration := time.Duration(5); p := &amp;amp;duration&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Please let me know in the comments if you like this; I'll try adding such bonus contents to my articles moving forward.&lt;/p&gt;

&lt;p&gt;Thanks for reading! For more content, please consider following.&lt;/p&gt;

&lt;p&gt;May the code be with you :)&lt;/p&gt;

&lt;p&gt;My Social Links: &lt;a href="https://linkedin.com/in/ashwingopalsamy" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="http://github.com/ashwingopalsamy" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;| &lt;a href="http://x.com/ashwin2125" rel="noopener noreferrer"&gt;𝕏 (formerly Twitter)&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.substack.com/" rel="noopener noreferrer"&gt;Substack &lt;/a&gt;| &lt;a href="https://dev.to/ashwingopalsamy"&gt;Dev.to&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>beginners</category>
      <category>pointers</category>
    </item>
    <item>
      <title>Installing Go on Windows 11 in One Command</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Thu, 14 Nov 2024 18:10:43 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/installing-go-on-windows-11-in-one-command-1dmm</link>
      <guid>https://dev.to/ashwingopalsamy/installing-go-on-windows-11-in-one-command-1dmm</guid>
      <description>&lt;h3&gt;
  
  
  Installing Go on Windows 11 in One Command
&lt;/h3&gt;

&lt;p&gt;If you’re setting up Go on Windows 11, it doesn’t get simpler than this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;winget &lt;span class="nb"&gt;install &lt;/span&gt;GoLang.Go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single command handles everything: downloading, installing, and configuring Go on your system. No manual work, no fiddling with settings—it’s exactly what you need to get started.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  A Few Quick Tips
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run as Admin&lt;/strong&gt;: Make sure your terminal or PowerShell is opened as an administrator. Without it, Winget won’t complete the install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify Installation&lt;/strong&gt;: Once it’s done, type &lt;code&gt;go version&lt;/code&gt; in the terminal to confirm Go is installed and ready to use. If it doesn’t show up, you might need to manually adjust your PATH (though Winget typically handles this for you).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Wrap-Up
&lt;/h3&gt;

&lt;p&gt;With Go installed in just one line, you’re all set to start coding. Whether you’re building microservices, exploring concurrency with Goroutines, or just testing out a new language, Go’s simplicity will get you up and running fast. Give it a try, and let the code do the talking. Happy coding!&lt;/p&gt;

</description>
      <category>go</category>
      <category>productivity</category>
      <category>windows</category>
      <category>macos</category>
    </item>
    <item>
      <title>Git Practices for Critical Production-grade Codebases</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Thu, 14 Nov 2024 05:38:20 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/git-practices-for-critical-production-grade-codebases-1if9</link>
      <guid>https://dev.to/ashwingopalsamy/git-practices-for-critical-production-grade-codebases-1if9</guid>
      <description>&lt;p&gt;TL;DR: Master Git with best practices for commits, branches, and PRs in production-grade systems. Learn to keep codebases clean, traceable, and reliable using tools like Commitlint.&lt;/p&gt;

&lt;p&gt;Git is the backbone of every software project. Whether you're debugging a critical issue, implementing a feature, or deploying to production, Git holds the story of your project’s evolution. But that story can get messy if we don’t follow some structure. Trust me, I’ve seen (and written) my share of cryptic commit messages and tangled branches, and it never ends well.&lt;/p&gt;

&lt;p&gt;Working in &lt;strong&gt;highly critical, production-grade FinTech systems&lt;/strong&gt;, I’ve learned that Git workflows are more than just a convenience—they’re a lifeline. Clean commits, branches, and pull requests (PRs) don’t just make life easier; they protect the stability of the systems we build, ensuring traceability and reducing risk in environments where the stakes couldn’t be higher.&lt;/p&gt;

&lt;p&gt;Here’s a guide to &lt;strong&gt;Git best practices&lt;/strong&gt; that I aim to follow (or at least aspire to), with tools to help you enforce these practices without adding too much overhead.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Commits: The Backbone of Your Codebase&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Your commit history is like a logbook. It should tell you exactly what happened and why, in a way that’s easy to follow. In production-grade systems, this clarity isn’t optional—it’s critical.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Write Atomic Commits&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;An atomic commit focuses on one thing—fixing a bug, adding a feature, or refactoring code. This ensures every commit is clear, self-contained, and easy to understand. It also makes debugging and rollbacks safer.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Good:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   feat: add endpoint for user account details
   fix: handle timeout in transaction service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bad:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   misc: fix bugs and add features
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I’m in a hurry, it’s tempting to lump everything into one commit, but I always regret it later when debugging becomes a nightmare.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;2. Use Descriptive Commit Messages&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Your commit message should explain &lt;strong&gt;what changed&lt;/strong&gt; and, if needed, &lt;strong&gt;why&lt;/strong&gt;. Following a consistent format helps everyone on the team (including your future self) understand what’s going on.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;subject&amp;gt;
&amp;lt;BLANK LINE&amp;gt;
&amp;lt;body (optional)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fix(auth): resolve token expiration issues in login&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feat(api): add batch endpoint for transaction summaries&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These messages don’t just help during reviews—they’re lifesavers when digging through logs or debugging an issue six months down the line.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;3. Automate Commit Linting&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;No matter how disciplined we are, it’s easy to slip up. That’s where &lt;strong&gt;Commitlint&lt;/strong&gt; comes in. It’s a lightweight tool that ensures your commit messages follow a defined convention, like &lt;strong&gt;Conventional Commits&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools for Commitlint:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/conventional-changelog/commitlint" rel="noopener noreferrer"&gt;Commitlint by Conventional Changelog&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is one of the most popular Commitlint tools. It’s simple, extensible, and works seamlessly with Husky to enforce commit message rules during pre-commit or pre-push hooks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/conventionalcommit/commitlint" rel="noopener noreferrer"&gt;Commitlint for Conventional Commits&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Written in &lt;strong&gt;Golang&lt;/strong&gt;, this lightweight Commitlint tool is fast and easy to set up for smaller teams or those already using Go. It’s perfect if you prefer tools that feel native to your tech stack. &lt;strong&gt;My personal favorite.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.conventionalcommits.org/" rel="noopener noreferrer"&gt;Conventional Commits Specification&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A useful guide to the conventions enforced by these tools.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Setting up Commitlint is straightforward, and the long-term benefits—clear commit messages, consistent history—are well worth the effort.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Branches: Organized and Traceable&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In highly critical systems, branch organization is non-negotiable. It’s not just about avoiding confusion—it’s about making sure work can be traced back to its purpose, especially in microservices architectures where each service lives in its own repository.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Follow a Consistent Naming Convention&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A good branch name starts with the task or issue identifier, making it easy to see what the branch is for. I always use this format:&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;JIRA-ticket-ID&amp;gt;-&amp;lt;type&amp;gt;-&amp;lt;short-description&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JIRA-5678-fix-transaction-timeout&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JIRA-1234-feature-add-batch-processing&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This convention has saved me—and my team—countless hours when tracking work across multiple repositories.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;2. Keep Branches Short-Lived&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The longer a branch stays open, the more likely it is to diverge from the base branch. I aim to merge branches into &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;develop&lt;/code&gt; frequently, keeping integration smooth and reducing conflicts.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;3. Rebase for a Clean History&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Rebasing instead of merging keeps your branch history linear, which is much easier to follow during debugging or reviews.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Workflow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout JIRA-5678-fix-transaction-timeout
git pull --rebase origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rebasing has saved me from so many messy histories, but I’m always careful not to rebase shared branches like &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Pull Requests: The Gateway to Collaboration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Pull requests are where collaboration happens. In highly critical systems, they also serve as an essential checkpoint to catch mistakes before they make it to production.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Use Clear and Structured PR Titles&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A PR title should be concise but informative. I use this format to keep things consistent and easily traceable:&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JIRA-ticket-ID] &amp;lt;Type&amp;gt;: &amp;lt;Short Description&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[JIRA-5678] Fix: Handle transaction timeout edge cases&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[JIRA-1234] Feature: Add bulk processing for transactions&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;2. Write Descriptive PR Descriptions&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A good PR description provides enough context to help reviewers understand what’s changing and why. I try to answer three key questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What changed?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why was this change made?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Does it introduce any risks or side effects?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### What
Added a batch endpoint for processing transaction summaries.

### Why
This improves efficiency for bulk transaction reconciliation.

### Impact
- Adds a new API endpoint.
- No breaking changes.
- Includes unit and integration tests.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  &lt;strong&gt;3. Keep PRs Small and Focused&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Large PRs are overwhelming to review and prone to mistakes. I aim to keep PRs focused on a single feature, bug, or task to make reviews faster and more effective.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;4. Use Checklists and Labels&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Checklists ensure that every step is complete before merging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Unit tests added&lt;/li&gt;
&lt;li&gt;[ ] Integration tests verified&lt;/li&gt;
&lt;li&gt;[ ] Documentation updated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Labels like &lt;code&gt;feature&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, or &lt;code&gt;hotfix&lt;/code&gt; also help prioritize reviews.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why These Practices Matter&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;highly critical, production-grade FinTech systems&lt;/strong&gt;, precision isn’t optional. I’ve seen how poor Git practices can snowball into major issues—long debugging sessions, delayed releases, or even customer-facing outages. Clean commits, structured branches, and clear PRs aren’t just best practices—they’re safeguards for the stability and trustworthiness of the systems we build.&lt;/p&gt;

&lt;p&gt;By following these practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debugging in production becomes faster and more efficient.&lt;/li&gt;
&lt;li&gt;Collaboration is smoother because everything is easy to trace.&lt;/li&gt;
&lt;li&gt;Compliance and audits are simpler, with clear histories and well-documented changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve got your own favorite tools or Git horror stories, let’s swap notes. The best practices we share today could save someone a lot of time (and stress) tomorrow.&lt;/p&gt;

&lt;p&gt;Glad you like it. May the code be with you. &amp;lt;3&lt;/p&gt;

&lt;p&gt;My Social Links: &lt;a href="https://linkedin.com/in/ashwingopalsamy" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="http://github.com/ashwingopalsamy" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;| &lt;a href="http://x.com/ashwin2125" rel="noopener noreferrer"&gt;𝕏 (formerly Twitter)&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.substack.com/" rel="noopener noreferrer"&gt;Substack &lt;/a&gt;| &lt;a href="https://dev.to/ashwingopalsamy"&gt;Dev.to&lt;/a&gt; | &lt;a href="https://ashwingopalsamy.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>productivity</category>
      <category>microservices</category>
    </item>
    <item>
      <title>The Ultimate Hack to Simplify Ctrl and Cmd Shortcuts Between Windows and Mac</title>
      <dc:creator>Ashwin Gopalsamy</dc:creator>
      <pubDate>Wed, 13 Nov 2024 17:55:07 +0000</pubDate>
      <link>https://dev.to/ashwingopalsamy/the-ultimate-hack-to-simplify-ctrl-and-cmd-shortcuts-between-windows-and-2hdk</link>
      <guid>https://dev.to/ashwingopalsamy/the-ultimate-hack-to-simplify-ctrl-and-cmd-shortcuts-between-windows-and-2hdk</guid>
      <description>&lt;p&gt;If you’ve ever sat down at a Windows machine after a long day on your Mac—or vice versa—you know the struggle. Your fingers instinctively hit the wrong key. You meant to copy, but instead, you’ve opened the Start menu. Or worse, you killed a process in the terminal. The &lt;code&gt;Ctrl&lt;/code&gt; vs &lt;code&gt;Cmd&lt;/code&gt; chaos is real, and as someone who hops between platforms daily, I know how frustrating it can be.&lt;/p&gt;

&lt;p&gt;For developers, where every keystroke counts, this constant back-and-forth isn’t just annoying—it’s exhausting. But here’s the good news: there’s a fix, and it’s surprisingly simple. All you need is Microsoft’s &lt;strong&gt;PowerToys&lt;/strong&gt;, a free, open-source tool that can tweak your Windows keyboard to match your Mac instincts.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Ctrl vs Cmd Struggle Is Universal
&lt;/h3&gt;

&lt;p&gt;If you’re a Mac-first developer like me, switching to a Windows keyboard feels like betrayal. You instinctively go for &lt;code&gt;Cmd+C&lt;/code&gt; to copy, only to realize that it’s actually &lt;code&gt;Ctrl+C&lt;/code&gt;. And if you’re coming from Windows, reaching for the &lt;code&gt;Ctrl&lt;/code&gt; key on a Mac often results in frustrated clicks and a string of internal curses. &lt;/p&gt;

&lt;p&gt;The problem isn’t just remembering which key does what; it’s rewiring your brain every time you switch systems. And as developers, we rely on muscle memory for productivity. Breaking that flow slows us down. &lt;/p&gt;




&lt;h3&gt;
  
  
  PowerToys to the Rescue
&lt;/h3&gt;

&lt;p&gt;Here’s where PowerToys comes in. It’s an open-source utility from Microsoft that’s a lifesaver for anyone who wants to customize their Windows experience. Among its many features, &lt;strong&gt;Keyboard Manager&lt;/strong&gt; lets you remap keys to make them work the way you want.  &lt;/p&gt;

&lt;p&gt;For me, that meant swapping &lt;code&gt;Ctrl&lt;/code&gt; and the &lt;code&gt;Alt&lt;/code&gt; key on my Windows keyboard so that it behaves more like my Mac. No more second-guessing every shortcut.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Setting It Up
&lt;/h4&gt;

&lt;p&gt;Here’s how to get started:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download PowerToys&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Grab it from &lt;a href="https://github.com/microsoft/PowerToys" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or directly from the Microsoft Store. It’s easy to install and lightweight.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enable Keyboard Manager&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Open PowerToys, go to the Keyboard Manager tab, and toggle it on.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remap Keys&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on &lt;em&gt;Remap a Key&lt;/em&gt;.
&lt;/li&gt;
&lt;li&gt;Choose the &lt;code&gt;Alt&lt;/code&gt; key as the original key and set it to act as &lt;code&gt;Ctrl&lt;/code&gt; (Windows’ equivalent of &lt;code&gt;Cmd&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;You can also remap the &lt;code&gt;Ctrl&lt;/code&gt; key to act as &lt;code&gt;Alt&lt;/code&gt; if you want full symmetry.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test It&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Open your IDE or favorite apps and try common shortcuts like copy, paste, and undo. You’ll notice how natural it feels almost instantly.  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Screenshot&lt;/strong&gt;&lt;/p&gt;

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




&lt;h3&gt;
  
  
  Why This Is a Game-Changer
&lt;/h3&gt;

&lt;p&gt;This simple tweak eliminates one of the biggest pain points of switching platforms. Instead of wasting mental energy remembering different key placements, your keyboard works &lt;em&gt;with&lt;/em&gt; you. For me, it’s been a small but meaningful change—one that helps me stay in the zone when coding, debugging, or even writing documentation.  &lt;/p&gt;




&lt;h3&gt;
  
  
  Bonus Productivity Tips
&lt;/h3&gt;

&lt;p&gt;While you’re exploring PowerToys, check out these other features that can make your life easier:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FancyZones&lt;/strong&gt;: Perfect for arranging multiple windows when you’re working across terminals, browsers, and IDEs.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PowerRename&lt;/strong&gt;: Quickly rename batches of files without leaving Explorer.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Explorer Preview&lt;/strong&gt;: View &lt;code&gt;.md&lt;/code&gt;, &lt;code&gt;.json&lt;/code&gt;, or other developer-centric file types directly in Explorer.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The Joy of a Seamless Workflow
&lt;/h3&gt;

&lt;p&gt;After making this change, I stopped thinking about which key to press and started focusing on my work. It’s funny how something so small can make such a big difference. If you’re juggling Windows and Mac and tired of playing “Ctrl or Cmd roulette,” give this a shot.  &lt;/p&gt;




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

&lt;p&gt;Have you tried PowerToys, or do you have your own hacks for handling multi-platform keyboard challenges? Share your tips—I’d love to hear them! &lt;/p&gt;

&lt;p&gt;If you have found value with this post, please support me with a like or comment. Your 3 seconds means a lifetime to me. &lt;/p&gt;

&lt;p&gt;Happy coding &lt;em&gt;(and less key taming)!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>macos</category>
      <category>windows</category>
      <category>keyboard</category>
    </item>
  </channel>
</rss>
