<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Vishnu Bharathi</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://vishnubharathi.codes/"/>
  <updated>2026-04-02T01:57:00.548Z</updated>
  <id>https://vishnubharathi.codes/</id>
  
  <author>
    <name>Vishnu Bharathi</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>2025: Year in review</title>
    <link href="https://vishnubharathi.codes/blog/2025-year-in-review/"/>
    <id>https://vishnubharathi.codes/blog/2025-year-in-review/</id>
    <published>2025-12-27T19:32:08.000Z</published>
    <updated>2026-04-02T01:57:00.548Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve always wanted to write a “year in review” blog post, and it’s finally happening here!</p><h2 id="Books"><a href="#Books" class="headerlink" title="Books"></a>Books</h2><p>I read 10 books this year.</p><ul><li><a href="https://www.goodreads.com/book/show/34507927-how-to-take-smart-notes">How to Take Smart Notes</a> - The first book I read this year. It helped me form a note-taking habit. It not only teaches how to take notes but also how to consume knowledge. Highly recommended to anyone.</li><li><a href="https://www.goodreads.com/book/show/39071691-the-bullet-journal-method">The Bullet Journal Method</a> - I picked this up to learn a journaling system. It led me to develop a journaling habit this year. I read it once and re-read parts of it throughout the year to clarify and reinforce certain aspects of the process.</li><li><a href="https://www.goodreads.com/book/show/1319.The_War_of_Art">The War of Art</a> - I discovered this via <a href="https://youtu.be/cpKsogGdem4?si=JjjjfgV8VcAAU0R9">this podcast episode</a> — I paused it midway to get the book. The book introduced me to the idea of resistance (which I discussed <a href="https://vishnubharathi.codes/blog/a-blogger-who-doesnot-blog/">here</a>) that every artist or creative individual faces.</li><li><a href="https://www.goodreads.com/book/show/14912777-turning-pro?from_search=true&amp;from_srp=true&amp;qid=Y4gu7WGOtC&amp;rank=1">Turning Pro</a> - This is a sequel to “The War of Art.” I kept both of these books on my table for a while. Whenever I felt distracted from work, I made myself pick up and read these books instead of doing something else. That usually helped me return to work energized.</li><li><a href="https://www.goodreads.com/book/show/202559882-self-led">Self-Led</a> - This book is about <a href="https://en.wikipedia.org/wiki/Internal_Family_Systems_Model">Internal Family Systems</a>. After reading it, I’ve been observing my “self” and noticing a phenomenon called “Parts Party” (the idea of how one thing leads to another emotionally). Overall, this has made me more self-aware and conscious of how I make others feel. I’m glad I picked up this book earlier this year.</li><li><a href="https://www.goodreads.com/book/show/35051973-dare-to-win">Dare to Win</a> - My daughter randomly chose this book in the bookstore and gave it to me. I took it as a sign from the universe and bought the book. I like reading these kinds of books when I feel low.</li><li><a href="https://www.goodreads.com/book/show/62313346-excellent-advice-for-living">Excellent Advice for Living: Wisdom I Wish I’d Known Earlier</a> - Assorted advice on a variety of things. Loved it!</li><li><a href="https://www.goodreads.com/book/show/17172479-a-little-book-of-life?from_search=true&amp;from_srp=true&amp;qid=bhKBS1BR31&amp;rank=7">A Little Book of Life</a> - Similar to the previous book, but this one is by Ruskin Bond (the author of many stories I’m reading these days to my daughter).</li><li><a href="https://www.goodreads.com/book/show/54898389-the-almanack-of-naval-ravikant?ref=nav_sb_ss_1_12">The Almanack of Naval Ravikant</a> - Soulful. Complete. Clear. This book calmed me down a lot. It had such a positive impact on me that I chose to gift a copy to my sister.</li><li><a href="https://www.goodreads.com/book/show/218272975-coding-interview-patterns?ref=nav_sb_ss_1_25">Coding Interview Patterns</a> - I chose to read this at the start of the year to overcome my anxiety about the job market and job security. A friend recommended it to me. It’s well written and did the job of reducing my anxiety.</li></ul><p>I also started a few more books that I couldn’t complete:</p><ul><li><a href="https://www.goodreads.com/book/show/218272975-coding-interview-patterns?ref=nav_sb_ss_1_25">Four Thousand Weeks</a> - I didn’t complete it, but it still had a great influence on me. I might re-read it from the start if I get the chance.</li><li><a href="https://www.goodreads.com/book/show/55723020-dopamine-nation?from_search=true&amp;from_srp=true&amp;qid=CrVvAMRlLs&amp;rank=1">Dopamine Nation</a> - I have been hearing to some podcasts about dopamine that has made me more mindful about how I spend my energy. I guess I ran out of dopamine to complete this book 😅 I will revisit this book only when I feel like I am misusing my dopamine.</li><li><a href="https://www.goodreads.com/book/show/11797471-the-idea-factory?ac=1&amp;from_search=true&amp;qid=FiUAoju8LL&amp;rank=1">The Idea Factory</a> - This books is about the engineers who worked at Bell Labs (The birthplace of various breakthrough technologies like Transistors, UNIX, C, etc.)</li><li><a href="https://www.goodreads.com/book/show/48581321-api-security-in-action?ref=nav_sb_ss_1_22">API Security in Action</a> - Left halfway because O’Reilly free trial ended ended - lol. But also I found what I was looking for. The thing that completed my journey here was reading through the docs of <a href="https://github.com/ory/hydra">Ory Hydra</a>.</li><li><a href="https://www.goodreads.com/book/show/126571502-postgresql-14-internals?ac=1&amp;from_search=true&amp;qid=sBXJfKOIlh&amp;rank=1">PostgreSQL 14 Internals</a> - My strategy for getting strong with Postgres is to read this book and look at what happened in the future releases of Postgres. It is kind of an intense book and demands certain level of energy.</li></ul><h2 id="Gadgets"><a href="#Gadgets" class="headerlink" title="Gadgets"></a>Gadgets</h2><p>I love trying out and using new gadgets. Here are some gadgets I got this year:</p><ul><li><a href="https://www.lenovo.com/in/en/p/laptops/thinkpad/thinkpadp/thinkpad-p16s-gen-2-16-inch-amd-mobile-workstation/len101t0075?orgRef=https%253A%252F%252Fwww.google.com%252F&amp;srsltid=AfmBOooFjstW_2aJ7f6Rgm3EP2NUqcCRBFKF0oRSvon2o1qrJWK66wny">ThinkPad P16s Gen 2</a> – I received a laptop refresh at work. Previously, I used a Dell XPS 15 and several older ThinkPads, so it was finally time for something new. My personal (and controversial) preference is still the XPS 15 over any ThinkPad. The good thing about ThinkPads is that Ubuntu runs smoothly on them out of the box.</li><li><a href="https://www.oneplus.in/product/oneplus-nord-buds-2r">OnePlus Nord Buds 2r</a> – I got these as a gift. I’ve always preferred wired audio devices—Apple EarPods (wired) have been my primary choice for the past five years. For some reason, I gave these wireless buds a try, and they’ve become my main audio device. I’ve overcome my “wired” obsession because wireless clearly wins in certain situations (for example, wireless is so much better than wired headphones while washing dishes).</li><li><a href="https://www.motorola.in/smartphones-motorola-razr-60/p?skuId=530&amp;srsltid=AfmBOooAUr_elu0FwzmFHN2dhWUfrwJylSnMx0XP1BudmYTQRvs_k9fZ">Moto razr 60</a> – I’ve been using the Moto g82 for the past three years and have wanted to try a foldable phone. I wished for a Samsung Galaxy Z Fold7, but it’s way out of my league price-wise. Hopefully, foldables will become more affordable in the future. I got my hands on the razr 60 in December, so it’s too soon to say much about it.</li><li><a href="https://www.saregama.com/carvaan">Saregama Carvaan</a> – This is my most loved gadget of the year (picture below). It comes loaded with playlists of retro songs. You can often find me carrying this box around the house and playing tunes whenever I feel like it. My favorite playlist is “Top 300.” Overall, I think I listened to more songs on this box than on Spotify this year.</li></ul><p><img width="702" height="575" alt="Pasted image 20251228000227" src="https://github.com/user-attachments/assets/14826472-3658-4d9a-a3bf-a6209fce4dc5" /></p><h2 id="Work"><a href="#Work" class="headerlink" title="Work"></a>Work</h2><ul><li>New title: “Staff Software Engineer” 🎉</li><li>This year marks half a decade with my current employer: <a href="https://hasura.io/">Hasura</a> / <a href="https://promptql.io/">PromptQL</a> and a full decade working at various startups.</li><li>What I have realized over these years is that, there are going to be ups and downs in every org. It is best to focus on learning and getting better and making the most out of our time.</li><li>The essence of my journey had been “show up, ship things, and help others ship” - I like it this way!</li></ul><h2 id="Finance"><a href="#Finance" class="headerlink" title="Finance"></a>Finance</h2><ul><li>🚗 Fixed my car loan.</li><li>💲 Fixed personal loans from the past.</li><li>🏦 Did decent in savings :)</li><li>Doing bad in investments, but it is okay for a guy who had been floating in loans from the past.</li></ul><h2 id="Events"><a href="#Events" class="headerlink" title="Events"></a>Events</h2><p>I showed up at only one in-person tech event this whole year. It was at BLR Go Meetup (Jan) - I helped with getting my employer to be the venue sponsor for this meetup. One thing I loved about this meetup was that they gave the mic to everyone in the room. They have to introduce themselves to the crowd and tell what they are looking to learn out of that meetup. I shared how I discovered Go programming in BMTC (public bus transport of Bangalore) and made a whole bunch of people to laugh/smile. Reflecting back, I feel like that is one of the proudest things I have done in 2025 - putting smiles on faces :)</p><p>I did get a chance to watch the recordings of a few conferences.</p><ul><li><a href="https://www.youtube.com/playlist?list=PLVl2hFL_zAh9DNkmJrGca4mT04f64CHbc">SOSS Days India</a></li><li><a href="https://fosdem.org/2025/schedule/track/go/">FOSDEM 2025 Go Videos</a></li><li>Some <a href="https://www.youtube.com/@GopherConEurope/videos">GopherCon EU 2025</a> videos</li><li>Currently active: <a href="https://www.youtube.com/watch?v=3mvD_Ud7HLY&amp;list=PL2ntRZ1ySWBeBA1lEnmD3vUedkRDvgnmw">GopherCon US 2025</a></li></ul><h2 id="Habits"><a href="#Habits" class="headerlink" title="Habits"></a>Habits</h2><p>Some habits that I formed this year:</p><ul><li>Taking notes while reading books</li><li>Bullet journal</li><li>Drinking coffee in the morning (successfully quit this too — lol :D)</li><li>Drinking tea in the evening (actively in the process of quitting this)</li><li>Switching to warm lighting at night</li><li>Maintaining less than an hour of screen time per day on mobile</li><li>Opening my journal instead of my phone as the first thing in the morning</li></ul><h2 id="Note-Taking"><a href="#Note-Taking" class="headerlink" title="Note Taking"></a>Note Taking</h2><p>I’m proud of my note-taking journey. I blogged about my note-taking setup <a href="https://vishnubharathi.codes/blog/my-note-taking-setup/">here</a> earlier this year. I’ve tweaked it a bit to fit into my bullet journal, but the core principles remain the same.</p><p>All my notes end up in my Obsidian vault. To celebrate my progress, I’m going to share my knowledge graph from Obsidian. This is how it looked around the start of the year:</p><p><img width="1440" height="1321" alt="Pasted image 20251228000250" src="https://github.com/user-attachments/assets/bebfae78-86fc-4263-bc75-83ceb02bde75" /></p><p>And this is how it looks now:</p><p><img width="1028" height="922" alt="Pasted image 20251227235946" src="https://github.com/user-attachments/assets/fc626f87-81f3-4468-b0f9-79db62ddda87" /></p><h2 id="Journals"><a href="#Journals" class="headerlink" title="Journals"></a>Journals</h2><p>This was the biggest productivity experiment I ran throughout the year. I chose bullet journals as my system for journaling. I remixed and adapted a few things, but overall I’m happy with the outcomes.</p><p>One thing I missed in my process was not reflecting enough. I want to improve in that aspect.</p><p>I think the bullet journal book clearly advocates using paper notebooks for journaling (analog). I ran a micro-experiment to go all digital with the help of Obsidian. The outcome: paper wins! I still use Obsidian, but mostly for notes and sometimes as a digital scratchpad. Paper notebooks are a clear winner—they can slow down time for you!</p><p><img width="1236" height="927" alt="Pasted image 20251228001807" src="https://github.com/user-attachments/assets/33ba14fb-137e-4608-be92-5a1738ca8f74" /></p><h2 id="Mantras"><a href="#Mantras" class="headerlink" title="Mantras"></a>Mantras</h2><p>Some things I needed to consciously repeat to myself — hopefully to ingrain them in my behavior:</p><ul><li>Order matters: Brush, Bath, Pray, Eat.</li><li>Do not talk about work with my wife.</li><li>Overcome Resistance.</li><li>Attention residue is real.</li><li>Acquire “Specific Knowledge” every day.</li><li>Calm down and observe the situation. You’ll find a way forward.</li><li>Watch your mood, rest up, and rejuvenate. </li><li>Meditate multiple times a day. Life has tangled so much that one won’t cut it.</li><li>Drop judgments. See what could be good in any situation.</li></ul><p>50% have become second nature to me. I am still working on the rest.</p><h2 id="Side-Projects"><a href="#Side-Projects" class="headerlink" title="Side Projects"></a>Side Projects</h2><p>I tried working on two side projects this year. Both of them flopped, and I had to stop working on them.</p><ul><li><a href="https://github.com/shinobistack/gokakashi">gokakashi</a> – Open source. Built with friends from work (mostly to deploy at work). Stack: Go + Postgres + Vite + React. We had to replace it with something like <a href="https://github.com/hasura/security-agent-tools">this</a>. This is a story in itself with a good deal of learning (saving it for another time).</li><li>A small app I built for my cousin with Next.js + Postgres + Tailwind + shadcn/ui. We had to throw it away because I struggled to find time to make it useful, and my cousin went back to doing things his old way. But this was a valuable learning experience for me. I probably tried out most of the AI-assisted coding tools in the market while working on this project and formed my opinions about them.</li></ul><p>If I have to set a goal for side projects, it would be to build something that stands the test of time.</p><p>~ ~ ~ ~</p><p>Overall, I feel good about all the progress I’ve made this year. I want to keep up the good work and focus on improving!</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I’ve always wanted to write a “year in review” blog post, and it’s finally happening here!&lt;/p&gt;
&lt;h2 id=&quot;Books&quot;&gt;&lt;a href=&quot;#Books&quot; class=&quot;hea
      
    
    </summary>
    
    
      <category term="life" scheme="https://vishnubharathi.codes/tags/life/"/>
    
      <category term="year-in-review" scheme="https://vishnubharathi.codes/tags/year-in-review/"/>
    
  </entry>
  
  <entry>
    <title>A blogger who doesn&#39;t blog</title>
    <link href="https://vishnubharathi.codes/blog/a-blogger-who-doesnot-blog/"/>
    <id>https://vishnubharathi.codes/blog/a-blogger-who-doesnot-blog/</id>
    <published>2025-11-08T11:54:56.000Z</published>
    <updated>2026-04-02T01:57:00.548Z</updated>
    
    <content type="html"><![CDATA[<p>I recently read this book called <a href="https://www.goodreads.com/book/show/1319.The_War_of_Art">The War of Art</a>. In the book, the author has introduced me to a new idea, which he calls “Resistance”.</p><p>To tell what that is, I must quote a few lines from the book:</p><blockquote><p>Most of us have two lives. The life we live, and the unlived life within us. Between the two stands Resistance…..</p><p>Are you a writer who doesn’t write, a painter who doesn’t paint, an entrepreneur who never starts a venture? Then you know what Resistance is.</p></blockquote><p>The moment I read those lines, I had this realization: “I have become <em>a blogger</em> who doesn’t blog.”</p><p>Today, I want to break that and overcome my resistance to writing blog posts. Because blogging is a soulful act for me. I find it personally rewarding every time I do it, and I always want to do more of it.</p><p>So, here I am! Opening up my journal in the middle of the night to write this blog post on paper to overcome my resistance. “Having to turn on my computer every time I want to write a blog post” has become a resistance for me. Not just that, I am sure there are <code>n</code> different things resisting me at a given point in time. But that is okay - I just need to do better at overcoming them!</p><p>I don’t know why, but I am finding it fun to write this on paper. The words are flowing faster, and I am saving myself from a little bit of screen time.</p><p>I want to do more of this: Resisting my resistance.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I recently read this book called &lt;a href=&quot;https://www.goodreads.com/book/show/1319.The_War_of_Art&quot;&gt;The War of Art&lt;/a&gt;. In the book, the a
      
    
    </summary>
    
    
      <category term="life" scheme="https://vishnubharathi.codes/tags/life/"/>
    
  </entry>
  
  <entry>
    <title>First User Framework</title>
    <link href="https://vishnubharathi.codes/blog/first-user-framework/"/>
    <id>https://vishnubharathi.codes/blog/first-user-framework/</id>
    <published>2025-06-04T15:07:03.000Z</published>
    <updated>2026-04-02T01:57:00.552Z</updated>
    
    <content type="html"><![CDATA[<p>I might have accidentally discovered a framework that tries to address work-life balance and side project burnout. For some engineers and builders, this might sound like “common sense”, but it took me a bit of time (a decade - lol) to arrive at this wisdom.</p><p>Here’s the thing: When you have an idea for a project (that light-bulb moment) or when a friend calls you up and says, “Hey, why don’t we build this side project?” your builder instinct kicks in and replies, “Let’s do it!”</p><p>That moment right there is causing a drift in your timeline. I want you to be conscious of that. The thing is, there are only 24 hours in a day, and by signing up to build this new project, you will devote a significant chunk of those hours to it. This might prevent you from doing other activities that are essential for your “work-life balance”.</p><p>How do you find time then? Well, you don’t need to find time for projects. Instead, try finding the right projects for your time.</p><h2 id="Who-is-this-for"><a href="#Who-is-this-for" class="headerlink" title="Who is this for?"></a>Who is this for?</h2><p>Before I continue, I would like to state that this piece of advice is contextual and doesn’t apply to everyone. This advice best applies to you if </p><ul><li>You have a full-time job.</li><li>You are living with your family (and looking to spend your precious evenings with them)</li><li>You are having trouble prioritizing “what to work on”, “what to study”, etc.</li><li>You are having trouble scheduling time.</li><li>You are having constant thoughts of building new projects.</li><li>You sometimes regret spending like 10 hours a week on a project that didn’t go anywhere.</li><li>(I guess you get it)</li></ul><h2 id="The-Framework"><a href="#The-Framework" class="headerlink" title="The Framework"></a>The Framework</h2><p>The truth is, you are building one of these:</p><ul><li>a project with no users</li><li>a project where you are the user</li><li>a project where you have a user (who is not you)</li></ul><p>When you start building a new project, it should fall under one of the above categories. It will eventually lead to one of the following outcomes:</p><ul><li>Best case: Your project is thriving and being used (hopefully by a good number of audience)</li><li>Average case: You hack on your project for a while and eventually forget about it.</li><li>Worst case: You question yourself, “What am I doing with my life?” after weeks/months (hopefully not “years”) of working on the project.</li></ul><p>Just like how most startups go nowhere, I am guessing that most of the side projects don’t hit the best-case outcome. They usually end up in worst or average-case outcomes. From my personal experience, I think I have been part of projects that fall under all (if not most) of the categories and outcomes defined above. Based on that, I have come to the following deduction:</p><table><thead><tr><th>Category</th><th>What you should do</th></tr></thead><tbody><tr><td>No users</td><td>Run away.</td></tr><tr><td>You are the user</td><td>Don’t build it.</td></tr><tr><td>You have a first user</td><td>Build it.</td></tr></tbody></table><blockquote><p><strong>First User Framework</strong>: Start a project only after you have the first user, who is ready to try it out and provide feedback from day 1.</p></blockquote><p> If a category 1 and 2 (no users and you are the user) project seems attractive to you, then challenge yourself to put yourself out there and turn it into category 3 (you have a first user) and then work on it. Instead of taking four months to build a project that no one uses, you will find yourself making meaningful progress in a week if you are able to qualify the project to be category 3 upfront. (we are looking at exponential time gains here; that should be more attractive to you)</p><p>On the other hand, this makes you ruthless about your time and priorities. You might already be working on a short-term goal that is important for you. At times like that, this framework will shine. Either your short-term goal is more important and you pass on the opportunity or this new “category 3” project becomes your short-term goal.</p><h2 id="But-my-passion-project"><a href="#But-my-passion-project" class="headerlink" title="But my passion project?"></a>But my passion project?</h2><p>Usually, passion projects fall under category 1 or 2. So this blog post makes me a villain in the eyes of passion projects. As I mentioned above, this framework is contextual and is written for people who are not finding time and balance in life. If you have the time and freedom to work on a passion project, you should probably do it! There is an immense sense of satisfaction that comes with it.</p><p>For example, I did a category 2 (passion) project: <a href="https://github.com/scriptnull/sblog">a small binary to kick-start my blog writing process</a>. I have been a solo user of it for the past 5 years. I have zero regrets about the time I put into it. So my point is not “don’t work on passion projects”. My point is “Be mindful of your time”.</p><p>~ ~ ~ ~</p><p>“But my friends are calling me to build the next Google?”</p><p>Well, attend the call and ask them, “Where is our first user?”</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I might have accidentally discovered a framework that tries to address work-life balance and side project burnout. For some engineers and
      
    
    </summary>
    
    
      <category term="career advice" scheme="https://vishnubharathi.codes/tags/career-advice/"/>
    
  </entry>
  
  <entry>
    <title>Nil channels in Go</title>
    <link href="https://vishnubharathi.codes/blog/nil-channels-in-go/"/>
    <id>https://vishnubharathi.codes/blog/nil-channels-in-go/</id>
    <published>2025-02-17T20:32:12.000Z</published>
    <updated>2026-04-02T01:57:00.556Z</updated>
    
    <content type="html"><![CDATA[<p>A friend from work messaged me today that they had a hard time because they had used <code>var c chan int</code> instead of <code>c := make(chan int)</code> in their Go code.</p><p>I responded by saying that I usually have one rule of thumb i.e. to always use of <code>make()</code> whenever I need a channel or map. That way I can be very sure that I can use those immediately.</p><p>They added that the surprising thing was it didn’t panic the program rather they ended up with an infinite loop that ran silently. I got more intrigued about the situation. So many questions started popping up in my mind. Why was I not able to catch it in the code review? Why was there no linter rule that could catch this? What is the point of having a nil channel in Go if I am brainwashing myself to always use <code>make()</code>?</p><p>I went on to get some answers and here they are!</p><h2 id="Nil-channel"><a href="#Nil-channel" class="headerlink" title="Nil channel"></a>Nil channel</h2><p>It is just a channel assigned to nil value.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> c <span class="keyword">chan</span> <span class="keyword">int</span></span><br></pre></td></tr></table></figure><p>Nothing wrong with it!</p><h2 id="Send-to-a-nil-channel"><a href="#Send-to-a-nil-channel" class="headerlink" title="Send to a nil channel"></a>Send to a nil channel</h2><p>When you try to send to a nil channel. </p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> c <span class="keyword">chan</span> <span class="keyword">int</span></span><br><span class="line">c &lt;- <span class="number">1</span></span><br></pre></td></tr></table></figure><p>You get a deadlock.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">fatal error: all goroutines are asleep - deadlock!</span><br><span class="line"></span><br><span class="line">goroutine 1 [chan send (nil chan)]:</span><br><span class="line">main.main()</span><br><span class="line">        &#x2F;home&#x2F;vishnu&#x2F;pers&#x2F;chanbug&#x2F;main.go:5 +0x1c</span><br><span class="line">exit status 2</span><br></pre></td></tr></table></figure><h2 id="Receive-from-a-nil-channel"><a href="#Receive-from-a-nil-channel" class="headerlink" title="Receive from a nil channel"></a>Receive from a nil channel</h2><p>When you try to receive a value from a nil channel</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> c <span class="keyword">chan</span> <span class="keyword">int</span></span><br><span class="line">&lt;-c</span><br></pre></td></tr></table></figure><p>You again get a deadlock.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">fatal error: all goroutines are asleep - deadlock!</span><br><span class="line"></span><br><span class="line">goroutine 1 [chan receive (nil chan)]:</span><br><span class="line">main.main()</span><br><span class="line">        &#x2F;home&#x2F;vishnu&#x2F;pers&#x2F;chanbug&#x2F;main.go:5 +0x17</span><br><span class="line">exit status 2</span><br></pre></td></tr></table></figure><h2 id="Send-and-Receive"><a href="#Send-and-Receive" class="headerlink" title="Send and Receive"></a>Send and Receive</h2><p>Now let us try doing both from a nil channel.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">var</span> c <span class="keyword">chan</span> <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">defer</span> <span class="built_in">close</span>(c)</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">c &lt;- i</span><br><span class="line">&#125;</span><br><span class="line">&#125;()</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i := <span class="keyword">range</span> c &#123;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>This ended up with deadlock too.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">fatal error: all goroutines are asleep - deadlock!</span><br><span class="line"></span><br><span class="line">goroutine 1 [chan receive (nil chan)]:</span><br><span class="line">main.main()</span><br><span class="line">        &#x2F;home&#x2F;vishnu&#x2F;pers&#x2F;chanbug&#x2F;main.go:15 +0x91</span><br><span class="line"></span><br><span class="line">goroutine 18 [chan send (nil chan)]:</span><br><span class="line">main.main.func1()</span><br><span class="line">        &#x2F;home&#x2F;vishnu&#x2F;pers&#x2F;chanbug&#x2F;main.go:11 +0x65</span><br><span class="line">created by main.main in goroutine 1</span><br><span class="line">        &#x2F;home&#x2F;vishnu&#x2F;pers&#x2F;chanbug&#x2F;main.go:8 +0x35</span><br><span class="line">exit status 2</span><br></pre></td></tr></table></figure><p>But my friend mentioned they ran into an infinite loop and not a deadlock. How so?</p><h2 id="The-for-select-construct"><a href="#The-for-select-construct" class="headerlink" title="The for select construct"></a>The <code>for select</code> construct</h2><p>My immediate suspicion was a <code>for select</code> construct instead of <code>for range</code> construct in the above program.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">var</span> c <span class="keyword">chan</span> <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">defer</span> <span class="built_in">close</span>(c)</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">c &lt;- i</span><br><span class="line">&#125;</span><br><span class="line">&#125;()</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i := &lt;-c:</span><br><span class="line">fmt.Println(i)</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Now that leads to an infinite loop without printing anything! Because <code>select</code> seems to not execute the <code>case i := &lt;-c</code> block when <code>c</code> is a nil channel. What can it do after all? It can’t really receive anything from an un-initialized nil channel, right? So it ignores the <code>case</code> block and always runs the <code>default</code> block again and again.</p><h2 id="Initialized-channel"><a href="#Initialized-channel" class="headerlink" title="Initialized channel"></a>Initialized channel</h2><p>Now let us initialize the channel by using <code>make(chan int)</code> instead of <code>var c chan int</code> to see how our dear friend <code>select</code> behaves.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">c := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">defer</span> <span class="built_in">close</span>(c)</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">c &lt;- i</span><br><span class="line">&#125;</span><br><span class="line">&#125;()</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i := &lt;-c:</span><br><span class="line">fmt.Println(i)</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>It was again an infinite loop, but this time the output was different. </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">$ go run main.go | head -n 10</span><br><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br></pre></td></tr></table></figure><p>The zeros took over the output. I had to pipe the output to <code>head</code> to stop the program from running infinitely and at the same time collect some sample output.</p><p>What are these zeros? Where are they coming from?</p><p>Those are arising from the <code>case i := &lt;-c</code> block of the select. When the channel is not nil, our select statement attempts to receive a value. That results in printing <code>1 2 3</code>, the three values that were sent to the channel. When we close a channel, all we get is the zero value. Hence we are getting zeros after that.</p><p>Is there a way to check if a channel is closed? yes, there is.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i, ok := &lt;-c:</span><br><span class="line"><span class="keyword">if</span> ok &#123;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)  <span class="comment">// this is still unreachable</span></span><br></pre></td></tr></table></figure><p>We avoided printing zeros, but it is still leading to an infinite loop. Because the select is alternating between <code>case</code> and <code>default</code> blocks and continuously executes them.</p><p>Let us get rid of <code>default</code>.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i, ok := &lt;-c:</span><br><span class="line"><span class="keyword">if</span> ok &#123;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)  <span class="comment">// this is still unreachable</span></span><br></pre></td></tr></table></figure><p>That didn’t prevent the infinite loop, our friend <code>select</code> is going on and on choose the <code>case i, ok := &lt;-c</code> block and performing the if condition that evaluates to false always as the channel is closed after sending 3.</p><h2 id="The-lesson"><a href="#The-lesson" class="headerlink" title="The lesson"></a>The lesson</h2><p>How do we avoid the infinite loop? Remember how the select statement ignored the <code>case</code> block when my friend accidentally used the nil channel instead of an initialized channel at the start of this post? That is exactly what we need to <strong>disable</strong> the case in the <code>select</code> statement.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i, ok := &lt;-c:</span><br><span class="line"><span class="keyword">if</span> !ok &#123;</span><br><span class="line">c = <span class="literal">nil</span></span><br><span class="line"><span class="keyword">break</span></span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>) <span class="comment">// this is still unreachable</span></span><br></pre></td></tr></table></figure><p>Now we are out of an infinite loop but are hitting a deadlock after the channel is closed.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">fatal error: all goroutines are asleep - deadlock!</span><br><span class="line"></span><br><span class="line">goroutine 1 [chan receive (nil chan)]:</span><br><span class="line">main.main()</span><br><span class="line">        &#x2F;home&#x2F;vishnu&#x2F;pers&#x2F;chanbug&#x2F;main.go:19 +0xa8</span><br><span class="line">exit status 2</span><br></pre></td></tr></table></figure><p>Because after we <strong>disable</strong> the case, the <code>select</code> statement essentially reduces to an empty <code>select</code> clause.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Makes the go routine sleep forever, there is no case statement that it can listen to for receiving a message.</p><p>The core lesson however is</p><blockquote><p>nil channels are useful for disabling <code>case</code> blocks of <code>select</code></p></blockquote><p>I kind of arrived at this lesson in a weird way, but <a href="https://www.youtube.com/watch?v=t9bEg2A4jsw">this just for func episode</a> teaches it in a beautiful way. (Thanks Campoy if you are reading this!)</p><p>This is particularly useful when you are dealing with multiple channels in different cases of a <code>select</code> and if you want to diable the case blocks one by one when those channels are no longer needed. Going to copy-paste the example from that justforfunc episode to capture the idea.</p><p>The problem is to merge values coming from two channels and output them in another channel.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">a := asChan(<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>)</span><br><span class="line">b := asChan(<span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>, <span class="number">8</span>)</span><br><span class="line">c := merge(a, b)</span><br><span class="line"><span class="keyword">for</span> v := <span class="keyword">range</span> c &#123;</span><br><span class="line">fmt.Println(v)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Now the <code>merge</code> routine could listen on both the channels and disable the case for a channel after it is closed to make sure that we don’t spend any more CPU time on that case.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">merge</span><span class="params">(a, b &lt;-<span class="keyword">chan</span> <span class="keyword">int</span>)</span> &lt;-<span class="title">chan</span> <span class="title">int</span></span> &#123;</span><br><span class="line">c := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">defer</span> <span class="built_in">close</span>(c)</span><br><span class="line"><span class="keyword">for</span> a != <span class="literal">nil</span> || b != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> v, ok := &lt;-a:</span><br><span class="line"><span class="keyword">if</span> !ok &#123;</span><br><span class="line">a = <span class="literal">nil</span></span><br><span class="line">log.Printf(<span class="string">&quot;a is done&quot;</span>)</span><br><span class="line"><span class="keyword">continue</span></span><br><span class="line">&#125;</span><br><span class="line">c &lt;- v</span><br><span class="line"><span class="keyword">case</span> v, ok := &lt;-b:</span><br><span class="line"><span class="keyword">if</span> !ok &#123;</span><br><span class="line">b = <span class="literal">nil</span></span><br><span class="line">log.Printf(<span class="string">&quot;b is done&quot;</span>)</span><br><span class="line"><span class="keyword">continue</span></span><br><span class="line">&#125;</span><br><span class="line">c &lt;- v</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;()</span><br><span class="line"><span class="keyword">return</span> c</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Beautiful, right? </p><p>Now back to our problem.</p><h2 id="The-solution"><a href="#The-solution" class="headerlink" title="The solution"></a>The solution</h2><p>Let me solve the rest of the problem just for closure.</p><p>One way would be to break to an <code>outer</code> label as shown below. That way, </p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">c := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">defer</span> <span class="built_in">close</span>(c)</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">c &lt;- i</span><br><span class="line">&#125;</span><br><span class="line">&#125;()</span><br><span class="line"></span><br><span class="line">outer:</span><br><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i, ok := &lt;-c:</span><br><span class="line"><span class="keyword">if</span> !ok &#123;</span><br><span class="line">c = <span class="literal">nil</span></span><br><span class="line"><span class="keyword">break</span> outer</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>And finally, we get</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">all done</span><br></pre></td></tr></table></figure><p>NOTE: this would work without the <code>c = nil</code> statement also.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">outer:</span><br><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i, ok := &lt;-c:</span><br><span class="line"><span class="keyword">if</span> !ok &#123;</span><br><span class="line"><span class="keyword">break</span> outer</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)</span><br></pre></td></tr></table></figure><p>If the above is same as the previous solution, what is the point? We noticed that setting a channel to <code>nil</code> is beneficial when we have multiple cases. In here, I could maybe use that as a check for the <code>for</code>.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">c := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">defer</span> <span class="built_in">close</span>(c)</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">c &lt;- i</span><br><span class="line">&#125;</span><br><span class="line">&#125;()</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> c != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">select</span> &#123;</span><br><span class="line"><span class="keyword">case</span> i, ok := &lt;-c:</span><br><span class="line"><span class="keyword">if</span> !ok &#123;</span><br><span class="line">c = <span class="literal">nil</span></span><br><span class="line"><span class="keyword">break</span></span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>I should probably start brainwasing myself to make sure I set the channel to <code>nil</code> after consuming it completely. That way I can avoid the weird break label syntax and disable select cases to get more throughput.</p><p>Anyhow I know of a simpler solution. So my recommended solution for my friend would be to</p><ul><li>initialize the channel with <code>make()</code></li><li>use a <code>for range</code> construct instead of <code>for select</code> construct.</li></ul><p>That would look like:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">c := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">defer</span> <span class="built_in">close</span>(c)</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">c &lt;- i</span><br><span class="line">&#125;</span><br><span class="line">&#125;()</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i := <span class="keyword">range</span> c &#123;</span><br><span class="line">fmt.Println(i)</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;all done&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="A-proverb"><a href="#A-proverb" class="headerlink" title="A proverb"></a>A proverb</h2><p>The example that I gave was a very “trimmed down” version of what my friend was trying to accomplish in a real-world system. He was trying to consume a channel and split the messages into two other channels. The miss was failing to <em>initialize</em> the channels where the split was occurring.</p><p>On the other end, we learned from the justforfunc example that, when we try to merge two channels into one, we could start setting the consumed channel(s) to nil.</p><p>This is provoking me to make up <a href="https://go-proverbs.github.io/">a Go proverb</a> of my own 😅 Please excuse me if it sounds bad! You have come so far. So you can’t escape from it now - lol :D</p><p>~ ~ ~ ~ </p><p>“Init when you split, Nil when you merge.”</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;A friend from work messaged me today that they had a hard time because they had used &lt;code&gt;var c chan int&lt;/code&gt; instead of &lt;code&gt;c := ma
      
    
    </summary>
    
    
      <category term="programming" scheme="https://vishnubharathi.codes/tags/programming/"/>
    
      <category term="go" scheme="https://vishnubharathi.codes/tags/go/"/>
    
  </entry>
  
  <entry>
    <title>My note-taking setup</title>
    <link href="https://vishnubharathi.codes/blog/my-note-taking-setup/"/>
    <id>https://vishnubharathi.codes/blog/my-note-taking-setup/</id>
    <published>2025-02-16T02:34:56.000Z</published>
    <updated>2026-04-02T01:57:00.556Z</updated>
    
    <content type="html"><![CDATA[<p>Some days back I shared something about note-taking on <a href="https://bsky.app/profile/vishnubharathi.codes/post/3lhuwdnwmr22i">the butterfly site</a> (don’t click on the hyperlink yet, it contains a spoiler to this post).</p><p>I have been doing this for a little over a month which makes me very underqualified for this post;  nevertheless, I feel like I have acquired a lifelong habit! Also, I am unable to keep quiet because of the pure joy I am finding in the process of it.</p><p>So let’s start!</p><h2 id="Notebook"><a href="#Notebook" class="headerlink" title="Notebook"></a>Notebook</h2><p> I keep a notebook and pen for taking notes.</p><p><img src="/images/afe27c0adef79e1a5e56feedd8df5f5b.jpg" alt=""></p><p>Cute? Check out the backside:</p><p><img src="/images/0cdec70774b185cc25d46d673a0529a2.jpg" alt=""></p><p>You might have noticed where I got it from. Yep, it is Miniso.</p><p>When I decided to start taking notes, I was searching for a particular kind of notebook and stumbled upon this empty one lying around in the house that satisfied the preconditions. So I kind of stole it from my wife. (She bought it in the first place and has been keeping it for future use)</p><p>Miniso is so good at making you buy stuff that you don’t need (ahem, ahem). Excuse me 😅 I don’t want to make you feel guilty for your last purchase from there. So I will rephrase it as they are so good in making you buy things that you will need for the future 😀</p><h2 id="Pen"><a href="#Pen" class="headerlink" title="Pen"></a>Pen</h2><p>We have ADD gel pens floating around everywhere, so it was my natural choice. These are very lightweight and thin (probably the thinnest pens I have ever used).</p><p>There are two variations that we have ADD gel Ceramic and ADD gel designer series. I generally carry the ceramic one.</p><p> IIRC I first used an ADD gel back in 2003. They used to be costly and with a wet ink which takes time to dry off. But these pens that I have now seem are on a different spectrum. They are more like ballpoint pens.</p><h2 id="The-Altman-technique"><a href="#The-Altman-technique" class="headerlink" title="The Altman technique"></a>The Altman technique</h2><p>Before I go on discussing how my setup works, we will take a short detour of what I call the “Altman technique” because my setup is a fork of the note-taking setup used by Sam Altman.</p><p>I learned this from this <a href="https://www.youtube.com/watch?v=apWjoXCxDcg">video</a>. His suggestions for note-taking are:</p><ul><li>You definitely want a spiral notebook.</li><li>You need to be able to tear off pages from the notebook (hence the spiral bind).</li><li>You want the notebook to lie flat when you open it and keep it on a surface. So you need a hardcover.</li><li>You want something that fits in the pocket.</li></ul><p>He likes ripping off pages from the notebook, and reading the notes by keeping the ripped-off pages side-by-side. He crumbles the pages and throws them out once he is done.</p><p>He seems to finish off one notebook within 2 or 3 weeks. That is a notebook of 100 pages. That is like 100 / (3*7) = 4.7 which is close enough to Niklas Luhmann (The creator of <a href="https://en.wikipedia.org/wiki/Zettelkasten">Zettelkasten</a>). Luhmann took 6 notes per day approx [^1]. Tell me the number of notes that you took in the last day/month/year, I will tell you the number of things you learned. To give an idea, Luhmann took 90,000 notes in his lifetime that helped him produce 58 books and hundreds of articles. So if you are running low on the amount of notes that you take per day/month/year, you will certainly need to retrospect your learning process.</p><p>One of the big mindset shifts that I had in Altman’s technique was “you have to tear pages off from your notebook” which is against the conventional note-taking technique that I have tried in school days: “Write something in your notebook and preserve those pages forever like it is history”. That is how you will end up with a pile of notebooks that go unnoticed and thrown away as time progresses.</p><p>What is the point of writing the page if all I am going to do is throw away the page at the end of the day? Well, you need to convert that note into an artifact that could be retrieved when you need it in the future. That usually means transferring the note to Zettelkasten (slip-box). While Altman doesn’t mention if he uses Zettelkasten, I guess his equivalent might be to use the note in a document/project he might be working on.</p><h2 id="How-I-use-them"><a href="#How-I-use-them" class="headerlink" title="How I use them"></a>How I use them</h2><p>I keep it open at that moment when I start reading a book, listening to a podcast, or watching a video.</p><p><img src="/images/666e4c25116c7775f5907d5fca6ecbea.jpg" alt=""></p><p>I pause the watching/reading when I want to take notes. I fill up a page and note its reference (book name, page number, etc.) at the bottom of the page. Most of the time I use both the front and back of the paper for a single note. So I mention the reference on one of those sides.</p><p>I was a bit skeptical if my notebook could be carried around easily in a pocket because of the weird form factor. But I was wrong. It is so good to carry around. But I stopped carrying them around in my pockets but I carry them in my backpack. Because I have found myself to be needing them usually when I sit for learning and not in situations like shopping.</p><p>What if that next big thought/idea strikes me while I am shopping? lol, no worries. because I will just note it down on my mobile. This is where I introduce you to my other notebook: <a href="https://obsidian.md/">Obsidian</a>.</p><p>When I am learning on my computer or mobile, I take my notes in Obsidian. This is the reason why I don’t carry the notebook in my pocket most of the time because I am mostly on my computer where I have Obsidian.</p><p>What do I do with the pages in my notebook? I do the same thing as Altman: tearing them off. Once in a while I sit down and feed my notes into Obsidian and then tear off the pages and throw it off. This is what the transfer looks like in the real world:</p><p><img src="/images/c148bac312b2440824a5638d42a61901.png" alt=""></p><p>I try to keep the lag between the syncing process to be small. I don’t like keeping a lot of notes in my notebook. I want to be ripping of as many pages from my notebook at any point in time as possible. Otherwise, I have to pay the taxes of <a href="https://en.wikipedia.org/wiki/Zeigarnik_effect">Zeigarnik effect</a> (the notes that I haven’t yet torn off and synced to my digital Zettelkasten will take up space which could be used for learning some other thing).</p><p>I also learned that I could use the Zeigarnik effect to my advantage: If I want to delve into the thoughts of a particular project for a certain period of time (say I want to have thoughts about this topic for the next week), I could just leave the notes in my notebook without tearing off and make them haunt me!</p><h2 id="The-Graph"><a href="#The-Graph" class="headerlink" title="The Graph"></a>The Graph</h2><p>Let us go back to where we started: <a href="https://bsky.app/profile/vishnubharathi.codes/post/3lhuwdnwmr22i">the butterfly site post</a> (you can click on it now)</p><p>It is a snapshot of the Obsidian graph. If you haven’t heard of Obsidian before, I don’t want to steal the joy of learning what Obsidian is from you. So I will not talk about it in detail here. I encourage you to <a href="https://obsidian.md/">see for yourself</a>! Besides I might do a post just about it at some point in the future.</p><p>But here is what you need to know. It is a note-taking app. You can implement Zettelkasten with it. You get an awesome graph view - a great dopamine hit every time you watch it. Here is what my graph looks like after 35 days of using it:</p><p><img src="/images/bbe530dcc2929d6b4b4e2aeeb19b4a78.png" alt=""></p><p>Looks pretty, huh?</p><p>[^1]: How to Take Smart Notes: One Simple Technique to Boost Writing, Learning and Thinking, page 91.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Some days back I shared something about note-taking on &lt;a href=&quot;https://bsky.app/profile/vishnubharathi.codes/post/3lhuwdnwmr22i&quot;&gt;the but
      
    
    </summary>
    
    
      <category term="life" scheme="https://vishnubharathi.codes/tags/life/"/>
    
      <category term=" productivity" scheme="https://vishnubharathi.codes/tags/productivity/"/>
    
  </entry>
  
</feed>
