<?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>Forem: Harutyun Mardirossian</title>
    <description>The latest articles on Forem by Harutyun Mardirossian (@crusty0gphr).</description>
    <link>https://forem.com/crusty0gphr</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%2F50319%2Fc29e4e03-c6f6-4b47-b571-084a01ed6587.jpeg</url>
      <title>Forem: Harutyun Mardirossian</title>
      <link>https://forem.com/crusty0gphr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/crusty0gphr"/>
    <language>en</language>
    <item>
      <title>Anti-pattern: Overwriting return value inside defer</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Wed, 09 Jul 2025 15:08:16 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/anti-pattern-overwriting-return-value-inside-defer-2259</link>
      <guid>https://forem.com/crusty0gphr/anti-pattern-overwriting-return-value-inside-defer-2259</guid>
      <description>&lt;p&gt;Over the years, I have observed numerous examples of code overriding the return value within a defer statement. This pattern is quite common in my professional experience. In almost every project I have been involved in, I have encountered this exact scenario at some point.&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;doSomething&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong"&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;doSomethingElse&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something else went wrong"&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;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&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;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doSomethingElse&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;doSomething&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many believe that the &lt;code&gt;f.run()&lt;/code&gt; function will return &lt;code&gt;errors.New(“something went wrong”)&lt;/code&gt;, as the &lt;code&gt;err = doSomethingElse()&lt;/code&gt; is considered the "root cause" of the error. However, the actual output of this function is &lt;code&gt;errors.New(“something else went wrong”)&lt;/code&gt; and here's why.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;f.run()&lt;/code&gt; function returns a named parameter &lt;code&gt;err&lt;/code&gt; (&lt;em&gt;Result Parameter&lt;/em&gt;) that is overwritten within the &lt;code&gt;defer&lt;/code&gt; statement. This approach is intended to stop the program’s execution if the &lt;code&gt;defer&lt;/code&gt; statement fails. While this may appear to be a clever solution, it can result in unexpected behavior and introduce bugs into the code.&lt;/p&gt;

&lt;p&gt;The first time I encountered this issue was while debugging a pool of workers that were randomly causing &lt;code&gt;invalid memory address or nil pointer dereference&lt;/code&gt;. My team and I were relatively new to Go. It was my first year after switching from PHP, and it took almost a week to identify the root cause of the problem.&lt;/p&gt;

&lt;p&gt;A few days ago, I came across a similar concept in my ongoing project. I posted a question on &lt;a href="https://www.linkedin.com/posts/crusty0gphr_go-golang-quiz-activity-7346530613820026880-NsY-" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to understand how many people are aware of this anti-pattern. This pattern can lead to unexpected behavior and bugs in the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Mechanism
&lt;/h2&gt;

&lt;p&gt;In the function signature &lt;code&gt;func run() (err error)&lt;/code&gt;, the variable &lt;code&gt;err&lt;/code&gt; is a result parameter. According to the Go specification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is declared and initialized to its zero value (nil for error types) upon entry to the function.&lt;/li&gt;
&lt;li&gt;It is treated like any other local variable within the function body. You can read from it and assign to it.&lt;/li&gt;
&lt;li&gt;Crucially, if the function executes a return statement without arguments (a "naked" return), the current value of the result parameter is what's returned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When function returns err, it's explicitly returning the current value of this specific variable. &lt;strong&gt;This variable err lives in the function's stack frame and acts as the designated memory location for the return value.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's trace the execution of &lt;code&gt;f.run()&lt;/code&gt; step-by-step.&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;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                                &lt;span class="c"&gt;// Step 1&lt;/span&gt;
    &lt;span class="k"&gt;defer&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="c"&gt;// Step 2&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;doSomethingElse&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;doSomething&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="c"&gt;// Step 3&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;                                                  &lt;span class="c"&gt;// Step 4&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&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;STEP 1:&lt;/strong&gt; The run function is called and the result parameter &lt;code&gt;err&lt;/code&gt; is declared and initialized within function's stack frame. Its initial value is &lt;code&gt;nil&lt;/code&gt; and &lt;strong&gt;is part of this frame.&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;+------------------------------------+
| run() Stack Frame                  |
+------------------------------------+
| err (Result Parameter): nil        | &amp;lt;-- the return slot
+------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STEP 2:&lt;/strong&gt; The &lt;code&gt;defer&lt;/code&gt; statement compiles into a closure. The closure captures a reference to the &lt;code&gt;err&lt;/code&gt; variable. This closure is then pushed onto a per-goroutine stack of deferred calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 3:&lt;/strong&gt; The expression err = doSomething() is executed. The error value is assigned to the result parameter &lt;code&gt;err&lt;/code&gt;. The value of &lt;code&gt;err&lt;/code&gt; in the stack frame is now &lt;code&gt;errors.New("something went wrong")&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------------------------+
| run() Stack Frame                  |
+------------------------------------+
| err (Result Parameter): "err_A"    | &amp;lt;-- "something went wrong"
+------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STEP 4:&lt;/strong&gt; In this step things are getting complicated. The &lt;code&gt;return&lt;/code&gt; statement triggers a two-phase process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The return expression is evaluated and locks in its current value as the value to be used for the return. &lt;code&gt;errors.New("something went wrong")&lt;/code&gt; for now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Before the function &lt;code&gt;f.run()&lt;/code&gt; officially returns control to &lt;code&gt;f.main()&lt;/code&gt;, the runtime executes any deferred calls in LIFO order. Inside the closure, the statement &lt;code&gt;err = doSomethingElse()&lt;/code&gt; is run. Because the closure holds a reference to the result parameter err, &lt;strong&gt;this assignment overwrites the value in &lt;code&gt;f.run()&lt;/code&gt;'s stack frame.&lt;/strong&gt; The value of the result parameter err is now &lt;code&gt;errors.New("something else went wrong")&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------------------------+
| run() Stack Frame                  |
|                                    |
|   +----------------------------+   |
|   | defer() closure executing  |   |
|   |                            |   |
|   | err = doSomethingElse()    | --+-\
|   +----------------------------+   | |
|                                    | |
| err (Result Parameter): "err_A"    | | &amp;lt;-- overwrites err
+------------------------------------+ |
                                       |
&amp;lt;--------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;defer&lt;/code&gt; completes the value of the result parameter err is overwritten.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------------------------+
| run() Stack Frame                  |
+------------------------------------+
| err (Result Parameter): "err_B"    | &amp;lt;-- "something else went wrong"
+------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function now completes its return sequence, returning the current value from the err slot. The value returned is &lt;strong&gt;"err_B"&lt;/strong&gt; or &lt;strong&gt;"something else went wrong"&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Danger
&lt;/h2&gt;

&lt;p&gt;At this point, you might ask a question: "But I don't see anything wrong here." Perhaps, if you have noticed the danger, my congratulations. Let’s have a beer together.&lt;/p&gt;

&lt;p&gt;Let’s take a look at the scenario I faced five years ago and explore the reasons behind the week-long debugging process during my junior year.&lt;/p&gt;

&lt;p&gt;A pool of parallel workers processing a huge file containing a list of JSON parameters. The idea was simple: read -&amp;gt; unmarshal into struct -&amp;gt; notify -&amp;gt; return the result in a channel.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;f.notify&lt;/code&gt; function was responsible for sending a message to Kafka. The &lt;code&gt;f.process()&lt;/code&gt; function itself was executed by the worker.&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;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="n"&gt;SomeType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="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="n"&gt;readAndUnmarshal&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&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;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resChan&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;SomeOtherType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="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="n"&gt;process&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;resChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;SomeOtherType&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="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;resChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;SomeOtherType&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;res&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;We were not provided with the exact content of the JSON file we were reading. Instead, we were given a small chunk, which were used to construct our result struct. The JSON keys may contain invalid values. For example, instead of an object, there might be a number. This will result in the unmarshaling failing, and an error will be returned.&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;res&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="n"&gt;readAndUnmarshal&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;   &lt;span class="c"&gt;// this return well be triggered&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This return statement will initiate the deferred closure’s execution. The &lt;code&gt;f.notify()&lt;/code&gt; will be executed, overriding the error returned by the &lt;code&gt;f.readAndUnmarshal()&lt;/code&gt; function with &lt;code&gt;nil&lt;/code&gt;. The return value of the &lt;code&gt;f.process()&lt;/code&gt; function when &lt;code&gt;f.readAndUnmarshal()&lt;/code&gt; fails will be &lt;code&gt;nil, nil&lt;/code&gt;. The worker will then push a &lt;code&gt;nil&lt;/code&gt; value to the channel &lt;code&gt;SomeOtherType{Result: nil}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the runtime, when accessing the field within the result of &lt;code&gt;f.worker()&lt;/code&gt;, the program will cause a panic.&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;// panic: runtime error: invalid memory address or nil pointer dereference&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;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SomeField&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The defer block completely broke the error path of the program. The required object was not initialized but was still returned. This error required a significant amount of time and effort to identify and rectify. Even experienced developers overlooked this error. I was able to reproduce this error by accidentally passing an empty JSON to be parsed.&lt;/p&gt;

&lt;p&gt;Honestly, I have no idea what the workers initially wrote in such a way. I also don't know the intention behind this design decision. The project was handed over in the ready-to-production state. Even unit tests were written in a way that &lt;code&gt;f.notify()&lt;/code&gt; guaranteed to fail, and this case was never tested.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unnamed return value scenario
&lt;/h3&gt;

&lt;p&gt;Let's also discuss the case when a function returns a local variable as an error. Here, the f.run() function will return &lt;code&gt;errors.New(“something went wrong”)&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;func&lt;/span&gt; &lt;span class="n"&gt;doSomething&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong"&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;doSomethingElse&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something else went wrong"&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;run&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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="c"&gt;// error is a local variable this time&lt;/span&gt;

    &lt;span class="k"&gt;defer&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;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doSomethingElse&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;doSomething&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&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 scenario, when &lt;code&gt;f.run()&lt;/code&gt; is called and A stack frame is created. It contains a slot for the local variable &lt;code&gt;err&lt;/code&gt; and a separate, anonymous slot for the return value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------------------------+
| run() Stack Frame                  |
+------------------------------------+
| __return_value_0 (hidden): nil     | &amp;lt;-- return slot
| err (local variable):     nil      | &amp;lt;-- local variable
+------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After executing &lt;code&gt;err = doSomething()&lt;/code&gt; the local err variable is updated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------------------------+
| run() Stack Frame                  |
+------------------------------------+
| __return_value_0 (hidden): nil     |
| err (local variable):     "err_A"  | &amp;lt;-- "something went wrong"
+------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point return is triggeted. &lt;strong&gt;This is the most important difference. The copy the value of the local err variable into the hidden return slot." This action happens before the defer is executed.&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;+------------------------------------+
| run() Stack Frame                  |
+------------------------------------+
| __return_value_0 (hidden): "err_A" | &amp;lt;-- RETURN VALUE IS NOW LOCKED IN
| err (local variable):      "err_A" |
+------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The deferred closure runs. &lt;strong&gt;It has a reference to the local &lt;code&gt;err&lt;/code&gt; variable, not the hidden return slot.&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;+------------------------------------+
| run() Stack Frame                  |
+------------------------------------+
| __return_value_0 (hidden): "err_A" | &amp;lt;-- Unchanged
| err (local variable):      "err_B" | &amp;lt;-- Overwritten
+------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The function returns the value from its hidden return slot. The value returned is "err_A".&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The return mechanism in Go is more complex because defer and named return values create a multi-step process that gives the programmer explicit control over the function's exit logic. This explicit two-phase process is a distinguishing feature of Go. In other languages, the process is more opaque. When a return is hit in a try block, the language runtime knows a finally block must run, but the interaction with the return value itself is often less defined and considered an anti-pattern to exploit.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Contexts: To Cancel or Not to Cancel</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Mon, 09 Jun 2025 07:26:24 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/contexts-to-cancel-or-not-to-cancel-5cc9</link>
      <guid>https://forem.com/crusty0gphr/contexts-to-cancel-or-not-to-cancel-5cc9</guid>
      <description>&lt;p&gt;In Go, the &lt;code&gt;context&lt;/code&gt; package provides a mechanism to &lt;strong&gt;propagate cancellation signals, deadlines, and request-scoped values&lt;/strong&gt; across API boundaries and goroutines. It enables &lt;strong&gt;graceful termination&lt;/strong&gt; of operations by allowing parent operations to cancel child operations. This prevents goroutine leaks and ensures resources are cleaned up efficiently when work is no longer needed.&lt;/p&gt;

&lt;p&gt;To shut down a chain of goroutines using &lt;code&gt;context&lt;/code&gt; in Go, you &lt;strong&gt;create a cancelable context that propagates cancellation signals&lt;/strong&gt; through the chain. Each goroutine monitors &lt;code&gt;ctx.Done()&lt;/code&gt; to exit cleanly when cancellation is requested.&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%2Fjw0lsm36qpq0gii3l8br.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%2Fjw0lsm36qpq0gii3l8br.png" alt="context cancelation diagram" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each caller must be able to cancel its callee, use context derivation and hierarchical cancellation. Each &lt;strong&gt;function creates a cancellable context for its callee&lt;/strong&gt;, enabling independent cancellation at any level.&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;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create child context for B (cancels when A exits or manually cancelled)&lt;/span&gt;
    &lt;span class="n"&gt;ctxA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancelA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancelA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Cancel B when A exits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&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;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create child context for C&lt;/span&gt;
    &lt;span class="n"&gt;ctxB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancelB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancelB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Cancel C when B exits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Hierarchy Creation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;main&lt;/code&gt; → &lt;code&gt;A&lt;/code&gt; with &lt;code&gt;ctx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; → &lt;code&gt;B&lt;/code&gt; with &lt;code&gt;ctxA&lt;/code&gt; (child of &lt;code&gt;ctx&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; → &lt;code&gt;C&lt;/code&gt; with &lt;code&gt;ctxB&lt;/code&gt; (child of &lt;code&gt;ctxA&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code below demonstrates hierarchical cancellation of goroutines using Go's context package.&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;"context"&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;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create child context for B (cancels when A exits or manually canceled)&lt;/span&gt;
    &lt;span class="n"&gt;ctxA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancelA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancelA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Cancel B when A exits&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Start B (no need to track separately)&lt;/span&gt;

    &lt;span class="c"&gt;// A's work&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="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="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&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="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;// Main cancelled us&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;"A: shutdown signal received"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&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;Millisecond&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A: working"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c"&gt;// Example: A decides to cancel B after 3 iterations&lt;/span&gt;
            &lt;span class="k"&gt;if&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;2&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;"A: manually cancelling B"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;cancelA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Cancel only B (not A itself)&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create child context for C&lt;/span&gt;
    &lt;span class="n"&gt;ctxB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancelB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancelB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Cancel C when B exits&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Start C&lt;/span&gt;

    &lt;span class="c"&gt;// B's work&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="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="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&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="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;// A cancelled us&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;"B: shutdown signal received"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&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;Millisecond&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"B: working"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// C's work&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="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="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&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="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;// B cancelled us&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;"C: shutdown signal received"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&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;Millisecond&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C: working"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&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="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;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Start chain&lt;/span&gt;

    &lt;span class="c"&gt;// Let run for 5 seconds&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;5&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;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;main: cancelling entire chain"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Cancel everything&lt;/span&gt;

    &lt;span class="c"&gt;// Allow time for shutdown messages&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;500&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;Millisecond&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;code&gt;A&lt;/code&gt; explicitly cancels &lt;code&gt;B&lt;/code&gt; after 3 iterations using its cancel function (&lt;code&gt;cancelA&lt;/code&gt;), which automatically propagates to &lt;code&gt;C&lt;/code&gt; since &lt;code&gt;C&lt;/code&gt;'s context is derived from &lt;code&gt;B&lt;/code&gt;'s. Meanwhile, the &lt;code&gt;main&lt;/code&gt; function cancels the entire chain after 5 seconds by calling its root cancel function, which propagates downward through all derived contexts.&lt;/p&gt;

&lt;p&gt;Each function monitors its own context's &lt;code&gt;Done()&lt;/code&gt; channel, allowing immediate termination when cancellation occurs. The defer &lt;code&gt;cancel()&lt;/code&gt; statements ensure child contexts are always properly cancelled when parents exit, preventing goroutine leaks. The output shows work progress interleaved with shutdown messages, demonstrating both targeted cancellation (&lt;code&gt;A&lt;/code&gt;→&lt;code&gt;B&lt;/code&gt;) and full-chain cancellation (&lt;code&gt;main&lt;/code&gt;→&lt;code&gt;A&lt;/code&gt;→&lt;code&gt;B&lt;/code&gt;→C&lt;code&gt;)&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>backend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>My Everyday Tools</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Sun, 17 Nov 2024 13:33:56 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/inside-my-workflow-2b04</link>
      <guid>https://forem.com/crusty0gphr/inside-my-workflow-2b04</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A craftsman is known by his tools.&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Jean de La Fontaine, a 17th-century French fabulist and poet&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a software engineer navigating the ever-evolving landscape of development, having a reliable toolchain is crucial to staying efficient and maintaining high-quality code. Over the years, I’ve curated a set of tools that streamline my workflow, from coding and testing to deployment and monitoring. Each tool in my arsenal serves a distinct purpose, and together, they form a cohesive ecosystem that boosts productivity while tackling complex projects. I’ll dive into the tools that shape my daily workflow as a developer, focusing on three key areas: my terminal setup, the TUI applications I rely on, and the desktop applications that streamline my tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. iTerm2 &lt;a href="https://iterm2.com" rel="noopener noreferrer"&gt;https://iterm2.com&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;iTerm2 is my terminal of choice because it combines power, flexibility, and convenience, making it indispensable for my workflow.&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%2Fpmfj17rovm0zx2hgxl1q.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%2Fpmfj17rovm0zx2hgxl1q.png" alt="iTerm2" width="800" height="587"&gt;&lt;/a&gt;&lt;br&gt;
For someone who spends a lot of time on the command line, iTerm2 strikes the ideal balance between performance and user-centric features, which is why it remains my go-to terminal. Here are some of its key features I really like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Split Panes:&lt;/strong&gt; Divide your terminal window into multiple panes, allowing you to run several sessions simultaneously within a single window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hotkey Window:&lt;/strong&gt; Access a terminal window instantly from any application using a customizable keyboard shortcut.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search Functionality:&lt;/strong&gt; Perform on-page searches with immediate highlighting of matches, including support for regular expressions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paste History:&lt;/strong&gt; Access a history of copied or pasted text, with options to save this history to disk for future reference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant Replay:&lt;/strong&gt; Rewind the terminal display to view past outputs, even if they've been overwritten or cleared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Triggers:&lt;/strong&gt; Set up actions that execute when specific text patterns appear, such as highlighting keywords or sending notifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Boop &lt;a href="https://github.com/IvanMathy/Boop" rel="noopener noreferrer"&gt;https://github.com/IvanMathy/Boop&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Boop is a free, open-source macOS application designed to simplify text manipulation tasks for developers.&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%2Fayphbyj8zx07rgur3qo5.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%2Fayphbyj8zx07rgur3qo5.png" alt="boop" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
It offers a straightforward interface where users can paste text and apply various operations, such as decoding URLs, formatting JSON, or converting data formats. Boop supports custom scripts, allowing users to extend its functionality to meet specific needs. By handling text processing locally, it enhances efficiency and security, eliminating the need to use online tools for these tasks. Boop offers a clean, minimalist interface where users can paste text and apply transformations with ease.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Zed &lt;a href="https://zed.dev" rel="noopener noreferrer"&gt;https://zed.dev&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;As a developer who’s deeply passionate about Rust and its potential, I couldn’t be more excited about Zed, the new high-performance code editor built entirely in Rust.&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%2Fgwrrj2qay7t2ksqvv9ip.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%2Fgwrrj2qay7t2ksqvv9ip.png" alt="zed" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
The creators of Atom and Tree-sitter have truly outdone themselves, crafting an editor that isn’t just fast, it’s lightning fast, leveraging multi-core CPUs and GPUs to redefine responsiveness. Zed’s real-time collaborative editing, or "multiplayer" mode, feels like the future of pair programming, seamlessly blending human collaboration with AI-powered code assistance. Features like multibuffers and inline evaluation take productivity to new heights, offering intuitive ways to navigate and edit sprawling codebases. The extensibility powered by Tree-sitter and WebAssembly is a dream for developers who love tinkering. For me, Zed represents everything I admire about Rust: speed, safety, and a focus on engineering excellence. It’s more than an editor; it’s a glimpse into the future of coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Obsidian &lt;a href="http://obsidian.md" rel="noopener noreferrer"&gt;http://obsidian.md&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Obsidian has become an indispensable tool for me, serving as both a note-taking powerhouse and my go-to platform for writing articles.&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%2Fhwwf6m93zzpnscou35pf.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%2Fhwwf6m93zzpnscou35pf.png" alt="obsidian" width="800" height="514"&gt;&lt;/a&gt;&lt;br&gt;
Built on Markdown files, it allows me to create, edit, and link notes seamlessly, creating a network of interconnected ideas that I can visualize through its interactive graph view. This non-linear approach is perfect for organizing thoughts and exploring relationships between concepts.&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%2Fxslp4jsqf19u9wh4odcl.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%2Fxslp4jsqf19u9wh4odcl.png" alt="obsidian" width="800" height="686"&gt;&lt;/a&gt;&lt;br&gt;
Key features like local storage ensure my notes are private and accessible offline, while its extensive customization options, including themes and plugins, let me tailor the app to fit my unique workflow. The active community around Obsidian adds to its power, offering plugins and themes that continually enhance its functionality. With optional features like Obsidian Sync for cross-device synchronization and Obsidian Publish for sharing notes online, it’s a truly flexible platform. Every article I write starts here, in the robust and distraction-free environment Obsidian provides, making it a cornerstone of my creative and professional workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminal tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Ollama &lt;a href="http://ollama.com" rel="noopener noreferrer"&gt;http://ollama.com&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Ollama is a game-changer for developers, offering an always-accessible AI companion that runs entirely on your local machine.&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%2Fa3jgt3ox0efl2uixd62s.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%2Fa3jgt3ox0efl2uixd62s.png" alt="ollama" width="800" height="587"&gt;&lt;/a&gt;&lt;br&gt;
With support for macOS, Linux, and Windows, it ensures data privacy while delivering the speed and flexibility developers need. Ollama's extensive library of large language models, including Llama and Mistral, can be seamlessly integrated into existing workflows thanks to its compatibility with the OpenAI Chat Completions API. Whether you need an AI to assist with coding, debugging, or brainstorming, Ollama is ready to work alongside you, on-demand, without relying on the cloud. Its ability to run locally makes it the perfect tool for privacy-conscious developers looking for a powerful yet customizable AI assistant. Some key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Execution:&lt;/strong&gt; Ollama allows users to run LLMs directly on their machines, mitigating privacy concerns associated with cloud-based solutions and providing faster processing speeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Library:&lt;/strong&gt; It provides access to a diverse collection of models, including Llama 3.2, Phi 3, Mistral, and Gemma 2, among others, allowing users to choose models that best fit their needs. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization:&lt;/strong&gt; Users can customize and create their own models, tailoring them to specific tasks or preferences.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Oh my zsh &lt;a href="https://ohmyz.sh" rel="noopener noreferrer"&gt;https://ohmyz.sh&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Oh My Zsh is a powerful, open-source framework that elevates the Z shell (Zsh) into a highly customizable and efficient command-line environment.&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%2Fyd75bbotzlbmg92163px.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%2Fyd75bbotzlbmg92163px.png" alt="ohmyzsh" width="800" height="248"&gt;&lt;/a&gt;&lt;br&gt;
Designed to simplify the management of Zsh configurations, it boasts an extensive library of over 300 plugins and themes, making it an indispensable tool for developers and power users. With support for popular tools and languages like Git, Docker, and Python, Oh My Zsh streamlines workflows and boosts productivity. By combining flexibility with ease of use, Oh My Zsh empowers users to create a personalized terminal setup that is both functional and visually appealing. Whether you're optimizing your workflow or simply sprucing up your terminal, Oh My Zsh provides the perfect balance of form and function.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. LazyDocker &lt;a href="https://github.com/jesseduffield/lazydocker" rel="noopener noreferrer"&gt;https://github.com/jesseduffield/lazydocker&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Lazydocker is an open-source terminal user interface (TUI) that simplifies managing Docker and Docker Compose environments.&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%2Flhb35oi3mbtps74mwgv6.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%2Flhb35oi3mbtps74mwgv6.png" alt="lazydocker" width="800" height="587"&gt;&lt;/a&gt;&lt;br&gt;
It provides a centralized interface where users can easily monitor and interact with containers, images, volumes, and networks. With features like real-time monitoring of logs and resource usage, container management tools for restarting or rebuilding services, and customizable commands, Lazydocker streamlines Docker workflows and enhances productivity. As a Go developer, I’m especially excited about Lazydocker because it showcases the power and versatility of Go in building practical, user-friendly tools that make everyday tasks more efficient and enjoyable. This tool is a perfect example of how Go can be leveraged to create something truly impactful for developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  4 NuShell &lt;a href="https://www.nushell.sh" rel="noopener noreferrer"&gt;https://www.nushell.sh&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Nushell is a modern, cross-platform shell that revolutionizes the command-line experience by introducing structured data handling and a rich programming language. Unlike traditional shells, Nushell processes data as typed tables, allowing seamless filtering, sorting, and transformations directly within the shell.&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%2F13t7sueid0yajvd3ydao.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%2F13t7sueid0yajvd3ydao.png" alt="nushell" width="" height=""&gt;&lt;/a&gt;&lt;br&gt;
It supports various data formats, including JSON, YAML, and Excel, and features built-in commands for tasks like HTTP requests, directory navigation, and file manipulation. Designed for Linux, macOS, Windows, and BSD, Nushell offers a unified, extensible experience across platforms. What makes Nushell even more exciting is that it’s written in Rust.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Helix Editor &lt;a href="https://helix-editor.com" rel="noopener noreferrer"&gt;https://helix-editor.com&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Helix is the final tool I recommend, and as a Vim alternative with batteries included, it’s a game-changer for modern developers. Built in Rust, Helix brings the speed, safety, and efficiency Rust is known for to the world of text editing.&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%2Fy81jfh2t3w6dipn0vuaw.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%2Fy81jfh2t3w6dipn0vuaw.png" alt="hx" width="800" height="587"&gt;&lt;/a&gt;&lt;br&gt;
It features a modal editing interface, inspired by Vim and Kakoune, that feels intuitive yet powerful, while offering advanced capabilities right out of the box. With multiple selections for simultaneous editing, Tree-sitter integration for precise syntax highlighting, and robust Language Server Protocol (LSP) support for code completion and diagnostics, Helix eliminates the need for extensive configuration or plugins. If you’re looking for a sleek, modern editor that pairs Vim’s philosophy with built-in features for today’s workflows, Helix is a must-try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I deliberately chose not to mention popular tools like VS Code, JetBrains, or mainstream database tools in this article. Instead, my focus was on highlighting processes and the lesser-known but equally powerful tools that often go unnoticed in the shadow of widespread hype. While those well-known tools are excellent, they’ve already had more than their share of attention on the web. My goal was to shine a light on the hidden gems that can truly enhance your workflow but might have been overlooked due to the overwhelming buzz surrounding the usual suspects. By exploring these alternatives, I hope to offer a fresh perspective and inspire you to discover tools that could revolutionize your approach to development.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>tooling</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding sync.Cond in Go: Synchronizing Goroutines in Producer-Consumer Scenarios</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Wed, 06 Nov 2024 07:51:17 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/understanding-synccond-in-go-synchronizing-goroutines-in-producer-consumer-scenarios-271i</link>
      <guid>https://forem.com/crusty0gphr/understanding-synccond-in-go-synchronizing-goroutines-in-producer-consumer-scenarios-271i</guid>
      <description>&lt;p&gt;In concurrent programming, synchronization is key to preventing data races and ensuring threads or goroutines operate in a coordinated manner. &lt;strong&gt;Imagine you have a problem to&lt;/strong&gt; coordinate multiple producers and consumers accessing a shared resource, such as a buffer or queue. This classic concurrency challenge is known as the &lt;strong&gt;producer-consumer problem&lt;/strong&gt;. In this scenario, synchronization is essential to ensure that producers do not overwrite data and consumers do not read invalid or stale data. Synchronisation is necessary, because without proper synchronization, simultaneous access to shared data can lead to race conditions, data corruption, or crashes. Producers need to wait if the buffer is full, and consumers need to wait if the buffer is empty. &lt;strong&gt;There might be scenarios&lt;/strong&gt; where you have a bounded buffer with a fixed size, and you need to manage access to it among multiple producers and consumers.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is &lt;code&gt;sync.Cond&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;sync.Cond&lt;/code&gt; in Go is a signaling mechanism that allows goroutines to wait until a specific condition is met. It’s particularly useful for coordinating complex workflows where some goroutines need to pause execution and wait until other goroutines complete certain actions. The ideas behind the &lt;code&gt;sync.Cond&lt;/code&gt; are pretty simple and easy to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blocking&lt;/strong&gt;: Goroutines can wait for a signal, pausing execution until notified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signaling&lt;/strong&gt;: Other goroutines can signal waiting goroutines to proceed when a condition is met.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt;: Reduces busy waiting by letting goroutines sleep until signaled.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How &lt;code&gt;sync.Cond&lt;/code&gt; Works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;sync.Cond&lt;/code&gt; Initialization&lt;/strong&gt;: It requires a &lt;code&gt;Locker&lt;/code&gt;, usually a &lt;code&gt;sync.Mutex&lt;/code&gt; or &lt;code&gt;sync.RWMutex&lt;/code&gt;, to control access. This &lt;code&gt;Locker&lt;/code&gt; helps guard shared resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Wait()&lt;/code&gt;&lt;/strong&gt;: When a goroutine calls &lt;code&gt;Wait()&lt;/code&gt;, it:

&lt;ul&gt;
&lt;li&gt;Releases the associated lock, allowing other goroutines to access the resource.&lt;/li&gt;
&lt;li&gt;Waits (blocks) until another goroutine signals it to continue.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;&lt;code&gt;Signal()&lt;/code&gt; and &lt;code&gt;Broadcast()&lt;/code&gt;&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Signal()&lt;/code&gt;&lt;/strong&gt; wakes up &lt;strong&gt;one&lt;/strong&gt; waiting goroutine, allowing it to acquire the lock and continue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Broadcast()&lt;/code&gt;&lt;/strong&gt; wakes up &lt;strong&gt;all&lt;/strong&gt; waiting goroutines.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Problem: Producer-Consumer with Mutex and Condition Variable
&lt;/h3&gt;

&lt;p&gt;Imagine you have a &lt;strong&gt;buffer&lt;/strong&gt; (or queue) with a fixed size. Multiple producers generate items and add them to the buffer, while multiple consumers remove items from it. The challenge is to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure producers only add items if there’s space in the buffer.&lt;/li&gt;
&lt;li&gt;Ensure consumers only remove items if the buffer is not empty.&lt;/li&gt;
&lt;li&gt;Signal producers and consumers when they can add or remove items.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the initial code structure:&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="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;bufferSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Buffer&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="kt"&gt;int&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;cond&lt;/span&gt; &lt;span class="o"&gt;*&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;Cond&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;produce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&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="c"&gt;// Producer logic to add item to the buffer&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;consume&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="c"&gt;// Consumer logic to remove item from the buffer&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&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;buffer&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;Buffer&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;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt; &lt;span class="o"&gt;=&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;NewCond&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;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&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="c"&gt;// Start producer goroutines&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;1&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;3&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="n"&gt;id&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="k"&gt;defer&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&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;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// Each producer creates 5 items&lt;/span&gt;
                &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;produce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&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;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Produce unique items based on id and j&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;100&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;Millisecond&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;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Start consumer goroutines&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;1&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;3&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="n"&gt;id&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="k"&gt;defer&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&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;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// Each consumer consumes 5 items&lt;/span&gt;
                &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;consume&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;"Consumer %d consumed item %d&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&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;150&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;Millisecond&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;i&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;"All producers and consumers finished."&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;Our task, as an engineer, is to implement &lt;code&gt;produce&lt;/code&gt; and &lt;code&gt;consume&lt;/code&gt; methods to achieve these requirements. The the &lt;code&gt;produce&lt;/code&gt; method adds items to the buffer and notifies consumers when an item is added. The &lt;code&gt;consume&lt;/code&gt; method removes items from the buffer and notifies producers when an item is removed. This problem can be seamlessly solved using &lt;code&gt;sync.Cond&lt;/code&gt; to wait and signal when the buffer is full or empty.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using &lt;code&gt;sync.Cond&lt;/code&gt; in the Example
&lt;/h3&gt;

&lt;p&gt;Here’s a breakdown of how &lt;code&gt;sync.Cond&lt;/code&gt; is used in the &lt;code&gt;produce&lt;/code&gt; and &lt;code&gt;consume&lt;/code&gt; methods:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;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="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt; &lt;span class="o"&gt;=&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;NewCond&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;buffer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Here, &lt;code&gt;sync.NewCond(&amp;amp;buffer.mu)&lt;/code&gt; creates a new condition variable associated with the &lt;code&gt;mu&lt;/code&gt; mutex. The condition variable enables waiting and signaling around changes to the buffer (like adding or removing items).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Producer Method (&lt;code&gt;produce&lt;/code&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;produce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&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;b&lt;/span&gt;&lt;span class="o"&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&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;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Wait if the buffer is full&lt;/span&gt;
    &lt;span class="k"&gt;for&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;bufferSize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&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="c"&gt;// Release lock and wait until signaled&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Add item to the buffer&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&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;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&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;"Produced item %d&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;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Signal a consumer that an item is available&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lock&lt;/strong&gt;: The producer locks &lt;code&gt;mu&lt;/code&gt; to ensure it has exclusive access to &lt;code&gt;b.data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait if Full&lt;/strong&gt;: If the buffer is full, the producer calls &lt;code&gt;b.cond.Wait()&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;This releases the lock on &lt;code&gt;b.mu&lt;/code&gt;, allowing a consumer to consume an item from the buffer.&lt;/li&gt;
&lt;li&gt;It waits (blocks) until a consumer signals that there’s now space in the buffer.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Add Item and Signal&lt;/strong&gt;: Once there’s space in the buffer, the producer:

&lt;ul&gt;
&lt;li&gt;Adds the item to the buffer.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;b.cond.Signal()&lt;/code&gt; to notify one waiting consumer (if any) that there’s now an item to consume.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Consumer Method (&lt;code&gt;consume&lt;/code&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;consume&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;b&lt;/span&gt;&lt;span class="o"&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&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;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Wait if the buffer is empty&lt;/span&gt;
    &lt;span class="k"&gt;for&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&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="c"&gt;// Release lock and wait until signaled&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Remove item from the buffer&lt;/span&gt;
    &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&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="n"&gt;b&lt;/span&gt;&lt;span class="o"&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;b&lt;/span&gt;&lt;span class="o"&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;1&lt;/span&gt;&lt;span class="o"&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;"Consumed item %d&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;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Signal a producer that space is available&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&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;item&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lock&lt;/strong&gt;: The consumer locks &lt;code&gt;mu&lt;/code&gt; to ensure exclusive access to &lt;code&gt;b.data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait if Empty&lt;/strong&gt;: If the buffer is empty, the consumer calls &lt;code&gt;b.cond.Wait()&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;This releases the lock on &lt;code&gt;b.mu&lt;/code&gt;, allowing a producer to produce an item and signal when it’s ready.&lt;/li&gt;
&lt;li&gt;The consumer waits until there’s an item to consume.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Consume Item and Signal&lt;/strong&gt;: Once there’s an item in the buffer, the consumer:

&lt;ul&gt;
&lt;li&gt;Removes it.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;b.cond.Signal()&lt;/code&gt; to notify a waiting producer that there’s now space in the buffer.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why &lt;code&gt;sync.Cond&lt;/code&gt; Is Effective Here
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Condition Variable&lt;/strong&gt;: &lt;code&gt;sync.Cond&lt;/code&gt; provides an efficient way to handle cases when the buffer is full or empty without looping unnecessarily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait and Signal Mechanism&lt;/strong&gt;: &lt;code&gt;Wait()&lt;/code&gt; automatically releases the lock, which prevents deadlocks by allowing other goroutines to proceed when appropriate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coordination&lt;/strong&gt;: By using &lt;code&gt;Signal()&lt;/code&gt;, we coordinate the actions of producers and consumers, ensuring that each waits only when necessary, preventing them from operating on an empty or full buffer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This coordination allows the producers and consumers to share the buffer without interference or deadlock, efficiently managing access based on the buffer’s state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Producers &lt;strong&gt;wait&lt;/strong&gt; if the buffer is full, and &lt;strong&gt;signal&lt;/strong&gt; consumers after producing an item.&lt;/li&gt;
&lt;li&gt;Consumers &lt;strong&gt;wait&lt;/strong&gt; if the buffer is empty, and &lt;strong&gt;signal&lt;/strong&gt; producers after consuming an item.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other Scenarios for &lt;code&gt;sync.Cond&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Imagine you have tasks where&lt;/strong&gt; multiple goroutines need to wait for a specific condition before proceeding, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Batch Processing&lt;/strong&gt;: Waiting until a certain number of tasks have accumulated before processing them together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Coordination&lt;/strong&gt;: Waiting for an event to occur (e.g., data to be loaded, a resource to become available).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting&lt;/strong&gt;: Controlling the number of concurrent operations to prevent resource exhaustion.
In these scenarios, &lt;code&gt;sync.Cond&lt;/code&gt; provides an efficient way to manage goroutine synchronization based on conditions, making it a right fit for problems requiring coordination among concurrent tasks.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Tricky Golang interview questions - Part 8: Max goroutine number</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Wed, 30 Oct 2024 13:24:06 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-8-max-goroutine-number-1ep2</link>
      <guid>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-8-max-goroutine-number-1ep2</guid>
      <description>&lt;p&gt;In Go interviews, one question that sometimes catches candidates off guard is about the "maximum number of goroutines that can be spawned." The answer isn’t as simple as stating a specific number. Instead, this question is typically used by interviewers to assess your understanding of Go’s concurrency model, memory management, and practical experience with goroutines.&lt;/p&gt;

&lt;p&gt;Here’s a concise guide to answering this question effectively:&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Go’s Concurrency Model and Goroutine Efficiency
&lt;/h3&gt;

&lt;p&gt;To start, it’s helpful to clarify that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Goroutines are lightweight, user-space threads managed by the Go runtime, making them much more efficient than traditional OS threads.&lt;/li&gt;
&lt;li&gt;Go doesn’t impose a strict cap on goroutines, and under the right conditions, you can spawn thousands or even millions of goroutines concurrently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A solid response would note that the practical limit largely depends on available system resources, especially memory, as each goroutine starts with a small stack size (about 2 KB). This lightweight design is why Go applications can handle massive concurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  System and Practical Limitations
&lt;/h3&gt;

&lt;p&gt;However, it’s crucial to acknowledge the limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory Consumption&lt;/strong&gt;: Each goroutine uses a small amount of memory for its stack, which grows as needed. While theoretically feasible to spawn millions, in practice, this can lead to high memory usage, especially when goroutines grow due to more complex processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduler Overhead&lt;/strong&gt;: Go’s runtime scheduler efficiently manages goroutines across OS threads, but with too many goroutines, it might become overwhelmed with scheduling, leading to context switching and potential performance issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This insight tells interviewers that you’re aware of Go’s scheduling efficiency, but also its boundaries in handling very high concurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  GOMAXPROCS and the Scheduler
&lt;/h3&gt;

&lt;p&gt;Next, demonstrate your understanding of Go’s scheduling mechanics by mentioning &lt;code&gt;GOMAXPROCS&lt;/code&gt;. This setting determines the number of OS threads that can execute goroutines concurrently, based on the number of logical CPUs. While &lt;code&gt;GOMAXPROCS&lt;/code&gt; doesn’t cap the number of goroutines, it does influence the level of concurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Tips and Best Practices
&lt;/h3&gt;

&lt;p&gt;It’s also beneficial to mention strategies for managing goroutines in real applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use patterns like &lt;strong&gt;worker pools&lt;/strong&gt; or &lt;strong&gt;rate limiting&lt;/strong&gt; to avoid unbounded goroutine creation, which can lead to resource exhaustion and degraded performance.&lt;/li&gt;
&lt;li&gt;Monitor goroutine usage in production with &lt;code&gt;runtime.NumGoroutine()&lt;/code&gt; to help keep tabs on active goroutines and identify potential leaks or excessive spawning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sample Answer Structure
&lt;/h3&gt;

&lt;p&gt;Here’s a sample answer that conveys a well-rounded understanding:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Go doesn’t set a hard limit on the number of goroutines; theoretically, you could spawn millions. However, the practical limit depends on factors like available memory and the scheduler’s ability to manage them efficiently. Each goroutine requires a small amount of memory, so with excessive goroutines, memory usage increases, and context switching can affect performance. &lt;code&gt;GOMAXPROCS&lt;/code&gt; controls concurrent OS threads for goroutines, but not the number of goroutines themselves.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This answer demonstrates a strong grasp of Go’s concurrency model, understanding system limitations, and showcases practical experience with goroutines a rounded response that interviewers will appreciate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus Section
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lets calculate how may goroutines can we run on specific hardware
&lt;/h3&gt;

&lt;p&gt;The theoretical number of goroutines a system can handle may be high, but real-world factors limit this number. &lt;strong&gt;Memory and CPU resources&lt;/strong&gt; are the primary bottlenecks when running a large number of goroutines.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example Scenario: Cloud Environment with 2 CPU Cores and 100 MB of RAM
&lt;/h4&gt;

&lt;p&gt;Let’s assume a cloud environment with &lt;strong&gt;2 CPU cores&lt;/strong&gt; and &lt;strong&gt;100 MB of RAM&lt;/strong&gt;. Here’s how to estimate the maximum number of goroutines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Memory Constraints&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Each goroutine begins with an approximate &lt;strong&gt;2 KB stack&lt;/strong&gt;, though it may grow depending on workload.&lt;/li&gt;
&lt;li&gt;With 100 MB of RAM, reserve &lt;strong&gt;20 MB&lt;/strong&gt; for Go’s runtime and system overhead, leaving around &lt;strong&gt;80 MB&lt;/strong&gt; for goroutines.&lt;/li&gt;
&lt;li&gt;Based on this, the theoretical upper bound would be: 


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Max Goroutines=80MB/0.002MB(2KB)​=40.000Max Goroutines = 80MB / 0.002MB (2KB)​ = 40.000
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord"&gt; &lt;/span&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;span class="mord mathnormal"&gt;oro&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;in&lt;/span&gt;&lt;span class="mord mathnormal"&gt;es&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;80&lt;/span&gt;&lt;span class="mord mathnormal"&gt;MB&lt;/span&gt;&lt;span class="mord"&gt;/0.002&lt;/span&gt;&lt;span class="mord mathnormal"&gt;MB&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mord mathnormal"&gt;K&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mord"&gt;​&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;40.000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;However, 40,000 is a rough estimate&lt;/strong&gt;, assuming each goroutine’s stack size stays minimal. This number decreases if goroutines require more stack space.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU Constraints&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;With &lt;strong&gt;2 CPU cores&lt;/strong&gt;, Go’s runtime can only execute &lt;strong&gt;2 OS threads concurrently&lt;/strong&gt; (if &lt;code&gt;GOMAXPROCS&lt;/code&gt; is set to 2).&lt;/li&gt;
&lt;li&gt;The Go scheduler handles goroutines across these threads, so if thousands of goroutines are running CPU-intensive tasks, context switching will add overhead, affecting performance.&lt;/li&gt;
&lt;li&gt;For a cloud instance with 2 cores, a practical goroutine count is often around &lt;strong&gt;1,000 to 5,000&lt;/strong&gt; depending on workload.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>go</category>
      <category>interview</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Result&lt;T, E&gt; type in PHP</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Sat, 26 Oct 2024 10:14:20 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/resultt-e-type-in-php-3dab</link>
      <guid>https://forem.com/crusty0gphr/resultt-e-type-in-php-3dab</guid>
      <description>&lt;p&gt;I've always been a huge fan of both Rust and GoLang. Their approaches to programming, particularly in error handling, have resonated with me throughout my career. After dedicating over four years to GoLang development, I recently transitioned to a project where I'm refactoring legacy PHP code into a newer, more robust version. This shift has been both exciting and challenging, especially when it comes to adapting to PHP's traditional error-handling mechanisms.&lt;/p&gt;

&lt;p&gt;Having grown accustomed to Go's "errors as values" concept, switching back to languages that rely on the conventional try-catch paradigm has been a significant adjustment. The idea of expecting the unexpected through exceptions feels counterintuitive. In GoLang, errors are treated as explicit return values that functions can produce, requiring developers to handle them directly. This explicitness promotes clarity and encourages thorough error checking at every function call.&lt;/p&gt;

&lt;p&gt;In contrast, exception-based error handling can sometimes lead to overlooked edge cases. It's possible to call a function that throws an exception and only discover the oversight in production when the application crashes a scenario every developer aims to avoid.&lt;/p&gt;

&lt;p&gt;To address this challenge, I decided to introduce a Rust-inspired &lt;code&gt;Result&lt;/code&gt; type in my PHP controller methods. Rust's approach to error handling, much like Go's, emphasizes returning results that explicitly indicate success or failure. By implementing a &lt;code&gt;Result&lt;/code&gt; type in PHP, I aimed to bring this level of explicitness and safety to my current project.&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%2F114a2esqxpvqlfhulq71.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%2F114a2esqxpvqlfhulq71.png" alt="php" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For instance, in the user registration endpoint, I wrapped Laravel’s validator to return a &lt;code&gt;Result&lt;/code&gt; containing either a valid value or an error. This modification allows me to explicitly handle validation failures, enabling the application to return a 422 Unprocessable Entity status code when appropriate. Not only does this make the error handling more transparent, but it also improves the API's reliability by ensuring that all potential errors are accounted for and managed properly.&lt;/p&gt;

&lt;p&gt;Here are some key benefits I've observed from this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enhanced Readability: By handling errors explicitly, the code becomes more readable and maintainable. Developers can see at a glance where errors might occur and how they're managed.&lt;/li&gt;
&lt;li&gt;Improved Reliability: Explicit error handling reduces the risk of uncaught exceptions causing unexpected crashes in production environments.&lt;/li&gt;
&lt;li&gt;Consistency Across Languages: Adopting a Result type in PHP brings the language's error-handling closer to that of Rust and GoLang, which can be beneficial for teams working across multiple languages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To provide a clearer picture of this methodology, I've prepared three code examples to highlight the contrasts and similarities between the languages and showcase how adopting certain patterns can lead to more robust and maintainable code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Golang
&lt;/h3&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%2Fbmkkn9qhxtcdoopi3bj3.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%2Fbmkkn9qhxtcdoopi3bj3.png" alt="go" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Rust
&lt;/h3&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%2Ftyp1481061fb0q5vbt4z.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%2Ftyp1481061fb0q5vbt4z.png" alt="rust" width="800" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm curious to hear your thoughts on this approach. Do you think incorporating concepts from one language into another is beneficial in the long run?&lt;/p&gt;

&lt;p&gt;Feel free to share your experiences or ask any questions.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>go</category>
      <category>php</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Best Resources for Learning Golang</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Sat, 07 Sep 2024 15:13:21 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/the-best-resources-for-learning-golang-51f6</link>
      <guid>https://forem.com/crusty0gphr/the-best-resources-for-learning-golang-51f6</guid>
      <description>&lt;p&gt;Hi there! I haven’t introduced myself yet, as I haven’t had the chance. My name is Harutyun {ha.root.eeoon}, and I’m a Software Engineer and passionate Golang Developer. I really adore the language and enjoy working with its toolchain. I’ve been working with Go for the past five years. Before switching to Golang, I worked as a Full Stack Developer, with PHP as my main backend language and JS + jQuery for the frontend.&lt;/p&gt;

&lt;p&gt;At that time, I noticed that many companies were transitioning to Golang from Ruby, NodeJS, and PHP to improve latency, introduce concurrency, and enable background task execution for their products. The first article I came across was on Shopify’s blog, explaining how switching to Golang improved their service latency by 80%. I was fascinated by the article and began reading up on references, language concepts, and Golang’s official blog to better understand the language.&lt;/p&gt;

&lt;p&gt;After PHP, Golang felt like a breath of fresh air—everything was fast, incredibly fast. I remember the first program I wrote: a file checksum validator for some open-sourced NASA data from the Apollo mission. It involved a collection of five files, each around 2GB in size. Seeing an execution time of 1.4 seconds blew my mind. At that moment, I knew I had to switch my stack to Golang to create and develop awesome software.&lt;/p&gt;

&lt;p&gt;In this article, I want to share some resources that helped me become a Golang Engineer and continue to help me develop new skills while staying up to date with the latest technologies. &lt;/p&gt;

&lt;h2&gt;
  
  
  Books: The Saint Triada
&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%2Fe1l2xf8j2sjka79wwdmf.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%2Fe1l2xf8j2sjka79wwdmf.png" alt="The Saint Triada" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Get Programming with Go&lt;/strong&gt; by Nathan Youngman and Roger Peppé
&lt;/h3&gt;

&lt;p&gt;If you’re just getting started with Go and want a book that makes the learning process easy and approachable, I highly recommend &lt;strong&gt;“Get Programming with Go”&lt;/strong&gt; by Nathan Youngman and Roger Peppé. This book is perfect for beginners because it really focuses on the basics without overwhelming you with too much information at once. What’s great about this book is how clearly it explains everything. It starts right from the ground up, walking you through the core concepts of Go step-by-step. You’ll learn the essentials like how to declare variables, use loops, and write functions, but the authors do it in a way that’s super accessible—even if you don’t have a ton of programming experience.&lt;/p&gt;

&lt;p&gt;If you’re new to Go or even new to programming in general, &lt;strong&gt;“Get Programming with Go”&lt;/strong&gt; is one of the best places to start. It’s designed to help you build a strong foundation in the language without feeling lost or frustrated, and by the time you’re finished, you’ll have a solid understanding of how Go works. One thing I really liked is that the book doesn’t assume you already know a bunch of other programming languages. It’s written in plain language and focuses on helping you understand Go’s syntax and structure in a simple, straightforward way. It also covers Go’s unique approach to things like error handling and memory management, but again, in a way that’s very beginner-friendly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Learning Go&lt;/strong&gt; by Jon Bodner
&lt;/h3&gt;

&lt;p&gt;If you’ve already gone through &lt;strong&gt;“Get Programming with Go”&lt;/strong&gt; and are looking to take your Go skills to the next level, I highly recommend following up with &lt;strong&gt;“Learning Go”&lt;/strong&gt; by Jon Bodner. While “Get Programming with Go” gives you a solid foundation and introduces the language in a very beginner-friendly way, &lt;strong&gt;“Learning Go”&lt;/strong&gt; goes deeper into the more complex aspects of the language, perfect for when you’re ready to explore Go in greater detail.&lt;/p&gt;

&lt;p&gt;This book builds on the basics and really helps you understand the intricacies of Go, like its concurrency model, interfaces, and error handling. Where the first book focuses on helping you get started, &lt;strong&gt;“Learning Go”&lt;/strong&gt; dives deeper into Go’s unique features, and it gives you a much clearer picture of how to write more efficient, maintainable code. The explanations are still very approachable, but they’re more comprehensive, covering concepts that you might not have tackled yet. So if you’ve finished “Get Programming with Go” and are ready for more depth, &lt;strong&gt;“Learning Go”&lt;/strong&gt; is the perfect next step. It’s a great way to continue your Go journey and really master the language.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;100 Go Mistakes and How to Avoid Them&lt;/strong&gt; by Teiva Harsanyi
&lt;/h3&gt;

&lt;p&gt;After building a solid foundation with &lt;strong&gt;“Get Programming with Go”&lt;/strong&gt; and diving deeper into Go’s core concepts with &lt;strong&gt;“Learning Go”&lt;/strong&gt;, the next logical step in mastering the language is &lt;strong&gt;“100 Go Mistakes and How to Avoid Them”&lt;/strong&gt; by Teiva Harsanyi. This book is the perfect continuation of your Go journey because it shifts the focus from learning the language to refining your skills and avoiding common pitfalls that even experienced developers encounter.&lt;/p&gt;

&lt;p&gt;Where the previous two books helped you understand how Go works and how to use its features, &lt;strong&gt;“100 Go Mistakes”&lt;/strong&gt; takes a more practical, hands-on approach by highlighting real-world mistakes that often trip up developers and how to steer clear of them. It’s a fantastic resource for developers who want to sharpen their expertise by learning from others’ experiences. The book covers mistakes across a wide range of topics, including concurrency, error handling, testing, and memory management, giving you insights into how to write more robust, efficient, and bug-free Go code. It’s not just about coding best practices, but about understanding the deeper reasons behind why certain approaches might seem right at first but can lead to subtle errors later. This book is invaluable for improving your Go skills, helping you think more critically about your code, and ensuring you avoid common traps as you progress toward writing more professional-level Go programs.&lt;/p&gt;

&lt;p&gt;Each book builds upon the previous one, ensuring a comprehensive learning journey from the basics to mastering Go’s intricacies. You start with &lt;strong&gt;“Get Programming with Go”&lt;/strong&gt; to establish a solid foundation, as it introduces the language in a simple, beginner-friendly way. &lt;strong&gt;“Learning Go”&lt;/strong&gt; then takes you deeper into Go’s core features and concepts, giving you a more thorough understanding of the language’s capabilities. Finally, &lt;strong&gt;“100 Go Mistakes and How to Avoid Them”&lt;/strong&gt; focuses on practical, real-world advice, helping you identify and avoid common pitfalls, making you a more efficient and confident Go developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  BONUS Book
&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%2Fgdkv3nxb1br0wqw7icy6.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%2Fgdkv3nxb1br0wqw7icy6.png" alt="BONUS Book" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Test-Driven Development in Go&lt;/strong&gt; by Adelina Simion
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;"Test-Driven Development in Go"&lt;/strong&gt; by Adelina Simion is the latest addition to my collection. With its fresh perspective and modern approach to TDD, this book will further solidify developers ability to write reliable, thoroughly tested Go code while keeping up with the latest development practices. This book will guide you through adopting test-driven development, ensuring that your Go code is not only functional but also robust and maintainable. By focusing on writing tests first and using them to guide your coding process, you’ll gain deeper insights into producing higher-quality code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blogs: Go Wisdom and Witty Wonders
&lt;/h2&gt;

&lt;h3&gt;
  
  
  research!rsc: Thoughts and links about programming, by Russ Cox
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://research.swtch.com" rel="noopener noreferrer"&gt;https://research.swtch.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s the personal blog of &lt;strong&gt;Russ Cox&lt;/strong&gt;, a key contributor to the Go programming language. Russ Cox is one of the original developers of Go and has written extensively about the language, its development, and software engineering concepts in general. His blog covers deep technical topics, particularly around Go’s design decisions, tooling, concurrency model, and performance optimizations. It’s an excellent resource for gaining insight into Go’s evolution and understanding the rationale behind many of the language’s features. Cox also writes about broader topics related to programming languages, compilers, and computer science theory. It’s a go-to for developers who want to dive into the intricacies of Go, and it offers unique perspectives on how Go is designed to solve practical problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dave Cheney: The acme of foolishness
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dave.cheney.net" rel="noopener noreferrer"&gt;https://dave.cheney.net&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dave Cheney is a prominent figure in the Go community and has contributed significantly to the language, particularly in areas like performance optimization, error handling, and best practices. His blog is well-known for providing in-depth, practical advice on writing idiomatic and efficient Go code. Topics he covers include Go’s concurrency model, memory management, testing strategies, and performance tuning. Dave is also known for breaking down complex topics in an accessible way, making his blog an excellent resource for both beginner and advanced Go developers. He has written about common Go design patterns, performance pitfalls, and how to get the most out of the language’s features, offering tips that help developers write more robust and maintainable Go programs. If you’re looking to deepen your understanding of Go or explore advanced techniques, Dave Cheney’s blog is a fantastic resource.&lt;/p&gt;

&lt;h3&gt;
  
  
  Julia Evans' Blog
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://jvns.ca" rel="noopener noreferrer"&gt;https://jvns.ca&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While Julia’s blog isn’t exclusively about Go, it’s well-known for its approachable and insightful posts on a wide range of technical topics, including systems programming, debugging, networking, and sometimes Go. Her writing style is casual and highly readable, making complex subjects easier to understand, even for beginners. One of the things that sets Julia apart is her ability to take intricate concepts whether it’s networking fundamentals or how operating systems work and break them down into simple, digestible posts. She often uses zines and illustrations to make technical content more engaging, which is a unique aspect of her blog. Even though Go is not the primary focus, when she does write about Go, it’s from a practical, systems-level perspective. If you’re into systems programming and want to see how Go fits into that world, Julia Evans’ blog is a great resource!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Go Blog
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://go.dev/blog/" rel="noopener noreferrer"&gt;https://go.dev/blog/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The official blog for the Go programming language, maintained by the Go team at Google. This blog covers new releases, features, design decisions, and community updates. It’s a great source for understanding Go from the perspective of the core developers. It’s the primary source of updates, news, and in-depth posts about the Go programming language, maintained by the core Go development team at Google. This blog covers a wide range of topics, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New Go releases&lt;/strong&gt;: Detailed explanations of what’s new in each version, including features, bug fixes, and improvements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language design decisions&lt;/strong&gt;: Insights into why certain features were added or how Go continues to evolve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best practices&lt;/strong&gt;: Articles on how to use Go more effectively, including tips on performance optimization, memory management, and concurrency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and ecosystem updates&lt;/strong&gt;: Highlights of community projects, Go conferences, and tools that enhance the Go ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Telegram channels
&lt;/h2&gt;

&lt;p&gt;Unfortunately, these are Russian-only channels, and most of the posts come from Russian sources, so they may not be a good fit for many. But if you know Russian, you’re all set!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@goproglib&lt;/strong&gt; - All the most useful things for a Go developer in one channel. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@go_in_action&lt;/strong&gt; - Everything about the Go programming language in Russian and English&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@golangtests&lt;/strong&gt; - Golang challenges&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@golang_interview&lt;/strong&gt; - Golang challenges and interview preparation resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Learning Go is a rewarding journey, and having the right resources makes all the difference. Whether you’re just starting out or looking to dive deep into more advanced concepts, the blogs and books mentioned here offer invaluable insights and guidance. From mastering the basics to avoiding common pitfalls, these resources have been carefully curated to ensure you can develop your Go skills effectively and confidently. &lt;/p&gt;

&lt;p&gt;As you continue exploring Go, remember that the strength of the Go community lies not only in its powerful language but also in its willingness to share knowledge. The resources available today reflect the hard work and dedication of countless contributors who want to help you succeed. Dive in, keep learning, and enjoy the process because with Go, the possibilities are endless!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Huge Thank You to the Go Community!
&lt;/h2&gt;

&lt;p&gt;I want to take a moment to express my appreciation for the incredible resources that have made learning Go such a rewarding experience. From in-depth blog posts on language design and performance to practical advice on writing efficient, idiomatic code, the contributions of so many in the community have been invaluable. The clarity, passion, and dedication behind these resources have helped countless developers, including myself, improve and grow.&lt;/p&gt;

&lt;p&gt;Thank you for making Go such an enjoyable and enriching journey for all of us!&lt;/p&gt;

</description>
      <category>go</category>
      <category>discuss</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Tricky Golang interview questions - Part 7: Data Race</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Fri, 06 Sep 2024 12:44:34 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-7-data-race-753</link>
      <guid>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-7-data-race-753</guid>
      <description>&lt;p&gt;Here is another code review interview question for you. This question is more advanced than the previous ones and is targeted toward a more senior audience. The problem requires knowledge of slices and sharing data between parallel processes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're not familiar with the slices and how they are constructed, please check out my previous article about the &lt;a href="https://dev.to/crusty0gphr/tricky-golang-interview-questions-part-1-slice-header-3oo0"&gt;Slice Header&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is a Data Race?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;data race&lt;/strong&gt; occurs when two or more threads (or goroutines, in the case of Go) concurrently access shared memory, and at least one of those accesses is a write operation. If there are no proper synchronization mechanisms (such as locks or channels) in place to manage access, the result can be &lt;strong&gt;unpredictable behavior&lt;/strong&gt;, including corruption of data, inconsistent states, or crashes.&lt;/p&gt;

&lt;p&gt;In essence, a data race happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two or more threads (or goroutines) access the same memory location &lt;strong&gt;at the same time&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;At least one of the threads (or goroutines) is &lt;strong&gt;writing&lt;/strong&gt; to that memory.&lt;/li&gt;
&lt;li&gt;There is &lt;strong&gt;no synchronization&lt;/strong&gt; to control the access to that memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of this, the order in which the threads or goroutines access or modify the shared memory is unpredictable, leading to non-deterministic behavior that can vary between runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     +----------------------+      +---------------------+
     | Thread A: Write      |      | Thread B: Read      |
     +----------------------+      +---------------------+
     | 1. Reads x           |      | 1. Reads x          |
     | 2. Adds 1 to x       |      |                     |
     | 3. Writes new value  |      |                     |
     +----------------------+      +---------------------+

                    Shared variable x
                    (Concurrent access without synchronization)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, Thread A is modifying x (writing to it), while Thread B is reading it at the same time. If both threads are running concurrently and there’s no synchronization, Thread B could read x before Thread A has finished updating it. As a result, the data could be incorrect or inconsistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question: One of your teammates submitted the following code for a code review. Please review the code carefully and identify any potential issues.&lt;/strong&gt;&lt;br&gt;
And here the code that you have to review:&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;"bufio"&lt;/span&gt;  
    &lt;span class="s"&gt;"bytes"&lt;/span&gt;
    &lt;span class="s"&gt;"io"&lt;/span&gt;
    &lt;span class="s"&gt;"math/rand"&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;genData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unix&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;  
    &lt;span class="n"&gt;buffer&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;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;512&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;_&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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&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="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&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;buffer&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;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="n"&gt;bufferSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;  
    &lt;span class="n"&gt;buffer&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;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="k"&gt;for&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;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&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="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&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;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EOF&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="k"&gt;return&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;n&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="k"&gt;break&lt;/span&gt;  
       &lt;span class="p"&gt;}&lt;/span&gt;  
       &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&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;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;consume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;scanner&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewScanner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
       &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  
       &lt;span class="c"&gt;// does the magic  &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;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;genData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="n"&gt;workersCount&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;  
    &lt;span class="n"&gt;chunkChannel&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="k"&gt;chan&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workersCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;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;workersCount&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="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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;chunkChannel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
             &lt;span class="n"&gt;consume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&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="p"&gt;}&lt;/span&gt;  

    &lt;span class="n"&gt;publish&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="n"&gt;chunkChannel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunkChannel&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;What we have here? &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;publish()&lt;/code&gt; function is responsible for reading the input data chunk by chunk and sending each chunk to the output channel. It begins by using &lt;code&gt;bytes.NewReader(input)&lt;/code&gt; to create a reader from the input data, which allows the data to be read sequentially. A buffer of size 8 is created to hold each chunk of data as it’s being read from the input. During each iteration, &lt;code&gt;reader.Read(buffer)&lt;/code&gt; reads up to 8 bytes from the input, and the function then sends a slice of this buffer (&lt;code&gt;buffer[:n]&lt;/code&gt;) containing up to 8 bytes to the output channel. The loop continues until &lt;code&gt;reader.Read(buffer)&lt;/code&gt; either encounters an error or reaches the end of the input data.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;consume()&lt;/code&gt; function handles the data chunks received from the channel. It processes these chunks using a &lt;code&gt;bufio.Scanner&lt;/code&gt;, which scans each chunk of data, potentially breaking it into lines or tokens depending on how it’s configured. The variable &lt;code&gt;b := scanner.Bytes()&lt;/code&gt; retrieves the current token being scanned. This function represents a basic input processing. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;main()&lt;/code&gt; creates a buffered channel chunkChannel with a capacity equal to &lt;code&gt;workersCount&lt;/code&gt;, which is set to 4 in this case. The function then launches 4 worker goroutines, each of which will read data from the &lt;code&gt;chunkChannel&lt;/code&gt; concurrently. Every time a worker receives a chunk of data, it processes the chunk by calling the &lt;code&gt;consume()&lt;/code&gt; function. The &lt;code&gt;publish()&lt;/code&gt; function reads the generated data, breaks it into chunks of up to 8 bytes, and sends them to the channel.&lt;/p&gt;

&lt;p&gt;The program uses goroutines to create multiple consumers, allowing for concurrent data processing. Each consumer runs in a separate goroutine, processing chunks of data independently.&lt;/p&gt;

&lt;p&gt;If you run this code, noting suspicious will happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.94&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is a problem. We have a &lt;strong&gt;Data Race Risk&lt;/strong&gt;. In this code, there’s a potential data race because the &lt;code&gt;publish()&lt;/code&gt; function reuses the same buffer slice for each chunk. The consumers are reading from this buffer concurrently, and since slices share underlying memory, multiple consumers could be reading the same memory, leading to a &lt;strong&gt;data race&lt;/strong&gt;. Let's try to use a race detection. Go provides a built-in tool to detect data races: the &lt;strong&gt;race detector&lt;/strong&gt;. You can enable it by running your program with the &lt;code&gt;-race&lt;/code&gt; flag:&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;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;race&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we add the &lt;code&gt;-race&lt;/code&gt; flag to the run command we will receive the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;race&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="o"&gt;==================&lt;/span&gt;
&lt;span class="n"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DATA&lt;/span&gt; &lt;span class="n"&gt;RACE&lt;/span&gt;
&lt;span class="n"&gt;Read&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;0x00c00011e018&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;goroutine&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slicecopy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOROOT&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;go1&lt;/span&gt;&lt;span class="m"&gt;.22.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;325&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0x0&lt;/span&gt;
  &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&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;Reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOROOT&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;go1&lt;/span&gt;&lt;span class="m"&gt;.22.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0xcc&lt;/span&gt;
  &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&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;Scanner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOROOT&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;go1&lt;/span&gt;&lt;span class="m"&gt;.22.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;219&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0xef4&lt;/span&gt;
  &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;consume&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOPATH&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0x140&lt;/span&gt;
  &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOPATH&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0x48&lt;/span&gt;

&lt;span class="n"&gt;Previous&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;0x00c00011e018&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="n"&gt;goroutine&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slicecopy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOROOT&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;go1&lt;/span&gt;&lt;span class="m"&gt;.22.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;325&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0x0&lt;/span&gt;
  &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&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;Reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOROOT&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;go1&lt;/span&gt;&lt;span class="m"&gt;.22.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;44&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0x168&lt;/span&gt;
  &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOPATH&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;27&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0xe4&lt;/span&gt;
  &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOPATH&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0xdc&lt;/span&gt;

&lt;span class="n"&gt;Goroutine&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;GOPATH&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0x50&lt;/span&gt;
&lt;span class="o"&gt;==================&lt;/span&gt;
&lt;span class="n"&gt;Found&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;race&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;exit&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="m"&gt;66&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.94&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The warning you’re seeing is a classic &lt;strong&gt;data race&lt;/strong&gt; detected by Go’s race detector. The warning message indicates that two goroutines are accessing the same memory location (&lt;code&gt;0x00c00011e018&lt;/code&gt;) concurrently. One goroutine is &lt;strong&gt;reading&lt;/strong&gt; from this memory, while another goroutine is &lt;strong&gt;writing&lt;/strong&gt; to it at the same time, without proper synchronization.&lt;/p&gt;

&lt;p&gt;The first part of the warning tells us that &lt;strong&gt;Goroutine 6&lt;/strong&gt; (which is one of the worker goroutines in your program) is reading from the memory address &lt;code&gt;0x00c00011e018&lt;/code&gt; during a call to &lt;code&gt;bufio.Scanner.Scan()&lt;/code&gt; inside the &lt;code&gt;consume()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read at 0x00c00011e018 by goroutine 6:
  runtime.slicecopy()
  /GOROOT/go1.22.0/src/runtime/slice.go:325 +0x0
  bytes.(*Reader).Read()
  /GOROOT/go1.22.0/src/bytes/reader.go:44 +0xcc
  bufio.(*Scanner).Scan()
  /GOROOT/go1.22.0/src/bufio/scan.go:219 +0xef4
  main.consume()
  /GOPATH/example/main.go:40 +0x140
  main.main.func1()
  /GOPATH/example/main.go:55 +0x48
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second part of the warning shows that the &lt;strong&gt;main goroutine&lt;/strong&gt; previously wrote to the same memory location (&lt;code&gt;0x00c00011e018&lt;/code&gt;) during a call to &lt;code&gt;bytes.Reader.Read()&lt;/code&gt; inside the &lt;code&gt;publish()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Previous write at 0x00c00011e018 by main goroutine:
  runtime.slicecopy()
  /GOROOT/go1.22.0/src/runtime/slice.go:325 +0x0
  bytes.(*Reader).Read()
  /GOROOT/go1.22.0/src/bytes/reader.go:44 +0x168
  main.publish()
  /GOPATH/example/main.go:27 +0xe4
  main.main()
  /GOPATH/example/main.go:60 +0xdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final part of the warning explains that &lt;strong&gt;Goroutine 6&lt;/strong&gt; was created in the main function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Goroutine 6 (running) created at:
  main.main()
  /GOPATH/example/main.go:53 +0x50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, while one &lt;strong&gt;goroutine (Goroutine 6)&lt;/strong&gt; is reading from the buffer in &lt;code&gt;consume()&lt;/code&gt;, the &lt;code&gt;publish()&lt;/code&gt; function in the main goroutine is simultaneously writing to the same buffer, leading to the data race.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------+               +--------------------+
|     Publisher     |               |      Consumer      |
+-------------------+               +--------------------+
        |                                   |
        v                                   |
1. Read data into buffer                    |
        |                                   |
        v                                   |
2. Send slice of buffer to chunkChannel     |
        |                                   |
        v                                   |
 +----------------+                         |
 |  chunkChannel  |                         |
 +----------------+                         |
        |                                   |
        v                                   |
3. Consume reads from slice                 |
                                            v
                                    4. Concurrent access
                                    (Data Race occurs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why the Data Race Occurs
&lt;/h3&gt;

&lt;p&gt;The data race in this code arises because of how Go slices work and how memory is shared between goroutines when a slice is reused. To fully understand this, let’s break it down into two parts: the behavior of the buffer slice and the mechanics of how the race occurs. When you pass a slice like &lt;code&gt;buffer[:n]&lt;/code&gt; to a function or channel, what you are really passing is the slice header which contains a &lt;strong&gt;reference&lt;/strong&gt; to the slice’s underlying array. Any modifications to the slice or the underlying array will affect all other references to that slice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;buffer = [ a, b, c, d, e, f, g, h ]  &amp;lt;- Underlying array
           ↑
          Slice: buffer[:n]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="n"&gt;bufferSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;  
    &lt;span class="n"&gt;buffer&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;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="c"&gt;// ....&lt;/span&gt;
       &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;// &amp;lt;-- passing is a reference to the underlying array&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 send &lt;code&gt;buffer[:n]&lt;/code&gt; to a channel, both the &lt;code&gt;publish()&lt;/code&gt; function and any consumer goroutines will be accessing the same memory. During each iteration, the &lt;code&gt;reader.Read(buffer)&lt;/code&gt; function reads up to 8 bytes from the input data into this buffer slice. After reading, the publisher sends &lt;code&gt;buffer[:n]&lt;/code&gt; to the output channel, where &lt;code&gt;n&lt;/code&gt; is the number of bytes read in the current iteration. &lt;/p&gt;

&lt;p&gt;The problem here is that &lt;strong&gt;buffer&lt;/strong&gt; &lt;strong&gt;is reused across iterations&lt;/strong&gt;. Every time &lt;code&gt;reader.Read()&lt;/code&gt; is called, &lt;strong&gt;it overwrites the data stored in buffer.&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Iteration 1&lt;/em&gt;: &lt;code&gt;publish()&lt;/code&gt; function reads the first 8 bytes into buffer and sends &lt;code&gt;buffer[:n]&lt;/code&gt; (say, &lt;code&gt;[a, b, c, d, e, f, g, h]&lt;/code&gt;) to the channel.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Iteration 2&lt;/em&gt;: The &lt;code&gt;publish()&lt;/code&gt; function overwrites the buffer with the next 8 bytes, let’s say &lt;code&gt;[i, j, k, l, m, n, o, p]&lt;/code&gt;, and sends &lt;code&gt;buffer[:n]&lt;/code&gt; again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, if one of the worker goroutines is still processing the first chunk, it is now reading stale or corrupted data because the buffer has been overwritten by the second chunk. &lt;strong&gt;Reusing a slice neans sharing the same memory&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to fix the Data Race?
&lt;/h3&gt;

&lt;p&gt;To avoid the race condition, we must ensure that each chunk of data sent to the channel has its &lt;strong&gt;own independent memory&lt;/strong&gt;. This can be achieved by creating a new slice for each chunk and copying the data from the buffer to this new slice. The key fix is to copy the contents of the buffer into a new slice &lt;strong&gt;before&lt;/strong&gt; sending it to the &lt;code&gt;chunkChannel&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="n"&gt;chunk&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;byte&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="c"&gt;// Step 1: Create a new slice with its own memory&lt;/span&gt;
&lt;span class="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;     &lt;span class="c"&gt;// Step 2: Copy data from buffer to the new slice&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;             &lt;span class="c"&gt;// Step 3: Send the new chunk to the channel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this fix works? By creating a new slice (chunk) for each iteration, you ensure that each chunk has its own memory. This prevents the consumers from reading from the buffer that the publisher is still modifying. &lt;code&gt;copy()&lt;/code&gt; function copies the contents of the buffer into the newly allocated slice (chunk). This decouples the memory used by each chunk from the buffer. Now, when the publisher reads new data into the buffer, it doesn’t affect the chunks that have already been sent to the channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------------+           +------------------------+
|  Publisher (New Memory) |           | Consumers (Read Copy)  |
|  [ a, b, c ] --&amp;gt; chunk1 |           |  Reading: chunk1       |
|  [ d, e, f ] --&amp;gt; chunk2 |           |  Reading: chunk2       |
+-------------------------+           +------------------------+
         ↑                                    ↑
        (1)                                  (2)
   Publisher Creates New Chunk          Consumers Read Safely
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solution works is that it breaks the connection between the publisher and the consumers by eliminating shared memory. Each consumer now works on its own copy of the data, which the publisher does not modify. Here’s how the modified &lt;code&gt;publish()&lt;/code&gt; function looks:&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;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bufferSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
    &lt;span class="n"&gt;buffer&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;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&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;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&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="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&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;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EOF&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&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;n&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="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Create a new slice for each chunk and copy the data from the buffer&lt;/span&gt;
        &lt;span class="n"&gt;chunk&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;byte&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="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="c"&gt;// Send the newly created chunk to the channel&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;chunk&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;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Slices Are Reference Types:&lt;/strong&gt;&lt;br&gt;
As mentioned earlier, Go slices are reference types, meaning they point to an underlying array. When you pass a slice to a channel or a function, you’re passing a reference to that array, not the data itself. This is why reusing a slice leads to a data race: multiple goroutines end up referencing and modifying the same memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory Allocation:&lt;/strong&gt;&lt;br&gt;
When we create a new slice with &lt;code&gt;make([]byte, n)&lt;/code&gt;, Go allocates a separate block of memory for that slice. This means the new slice (chunk) has its own backing array, independent of the buffer. By copying the data from &lt;code&gt;buffer[:n]&lt;/code&gt; into chunk, we ensure that each chunk has its own private memory space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decoupling Memory:&lt;/strong&gt;&lt;br&gt;
By decoupling the memory of each chunk from the buffer, the publisher can continue to read new data into the buffer without affecting the chunks that have already been sent to the channel. Each chunk now has its own independent copy of the data, so the consumers can process the chunks without interference from the publisher.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preventing Data Races:&lt;/strong&gt;&lt;br&gt;
The main source of the data race was the concurrent access to the shared buffer. By creating new slices and copying the data, we eliminate the shared memory, and each goroutine operates on its own data. This removes the possibility of a race condition because there’s no longer any contention over the same memory.&lt;/p&gt;

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

&lt;p&gt;The core of the fix is simple but powerful: by ensuring that each chunk of data has its own memory, we eliminate the shared resource (the buffer) that was causing the data race. This is achieved by copying the data from the buffer into a new slice before sending it to the channel. With this approach, each consumer works on its own copy of the data, independent of the publisher’s actions, ensuring safe concurrent processing without race conditions. This method of decoupling shared memory is a fundamental strategy in concurrent programming. It prevents the unpredictable behavior caused by race conditions and ensures that your Go programs remain safe, predictable, and correct, even when multiple goroutines are accessing data concurrently.&lt;/p&gt;

&lt;p&gt;It's that easy!&lt;/p&gt;

</description>
      <category>go</category>
      <category>interview</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Tricky Golang interview questions - Part 6: NonBlocking Read</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Wed, 10 Jul 2024 08:11:36 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-6-nonblocking-read-aj1</link>
      <guid>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-6-nonblocking-read-aj1</guid>
      <description>&lt;p&gt;This problem is more related to code review. It requires knowledge about channels and select cases, also blocking, making it one of the most difficult interview questions I faced in my career. In these kinds of questions, the context is unclear at first glance and requires a deep understanding of blocking and deadlocks. While previous articles mostly targeted advanced junior or entry-level middle topics, this one is a more senior-level problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question: One of your teammates submitted this code for a code review. This code has a potential threat. Identify it and give a solution to solve it.&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;ch&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="k"&gt;chan&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;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;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sent: 42"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&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;"Received:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&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;"Continuing execution..."&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;At first glance nothing suspicious in this code. If we try to run it it will actually compile and run without any noticeable problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="n"&gt;Sent&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;Received&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;Continuing&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;2.124&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code itself also seems fine. We have concurrent consumption implemented correctly with 2 goroutines working independently. Let's break down the code and see what's happening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; A channel &lt;code&gt;ch&lt;/code&gt; is created with &lt;code&gt;make(chan int)&lt;/code&gt;. This is an unbuffered channel.&lt;/li&gt;
&lt;li&gt; A goroutine is started that sleeps for 2 seconds and then sends the value 42 to the channel.&lt;/li&gt;
&lt;li&gt;The main function performs a read operation on ch with &lt;code&gt;val := &amp;lt;-ch&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again seems fine. But what we actually have here is, that the send operation is delayed. The anonymous goroutine waits for 2 seconds before sending the value into the channel. So when we run this code the main function starts reading the channel and expects a value in there before the channel gets populated with a value. &lt;strong&gt;This operation blocks the further execution of the code.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Read operations on empty channels
&lt;/h3&gt;

&lt;p&gt;In Go, when you try to read from an empty channel, the read operation blocks until a value becomes available. This means that the goroutine performing the read will be paused and will not proceed with further operations until it can successfully read a value from the channel.&lt;/p&gt;

&lt;p&gt;When the code performs a read operation on a channel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unbuffered Channel&lt;/strong&gt;: If the channel is unbuffered and no value is available, the read operation will block until another goroutine sends a value to the channel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffered Channel&lt;/strong&gt;: If the channel is buffered, the read operation will block if the buffer is empty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The delay of 2 seconds won't be that noticeable in this case and the one who observes the execution won't even notice the gap, but from the runtime perspective, the whole execution flow was &lt;strong&gt;stalled for 2 seconds&lt;/strong&gt;. Until the value 42 is sent after 2 seconds, the main goroutine is blocked on &lt;code&gt;val := &amp;lt;-ch&lt;/code&gt;. A blocking read halts all subsequent code execution until the read operation completes. This can lead to a program that appears to be frozen if there is no other goroutine sending data to the channel. If more operations are supposed to follow, they are delayed.&lt;/p&gt;

&lt;p&gt;In the real-world scenarios, for example, we have created a mini-Youtube application. One of the heaviest components for Youtube is the video encoder, which, for example, is represented as a pool of worker services.&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%2Fie6vpgczueaj76y6n0aj.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%2Fie6vpgczueaj76y6n0aj.png" alt="mini-youtube-abstarct-diagram" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process of video encoding can take anywhere from a few minutes to several hours. Imagine our main function sends a 24-hour long video to the encoder, which might take 3-4 hours to process. Everything written after the channel read line will be blocked for hours. Consequently, your backend will be unable to perform any other tasks until the video encoding is complete. If you increase the sleep timer to 20 seconds  &lt;code&gt;time.Sleep(20 * time.Second)&lt;/code&gt; you will notice how long it takes until the last print statement appears in the output log. &lt;/p&gt;

&lt;h3&gt;
  
  
  Consequences of Blocking
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;As we already discussed, a blocking read halts all subsequent code execution until the read operation completes. This can lead to a program that appears to be frozen if there is no other goroutine sending data to the channel.&lt;/li&gt;
&lt;li&gt;May cause serious concurrency issues. If the main goroutine (or any critical goroutine) blocks indefinitely waiting for data, it can prevent other important tasks from executing, leading to deadlocks or unresponsive behaviour.&lt;/li&gt;
&lt;li&gt;Resource utilization problems. While blocked, the goroutine does not consume CPU resources actively, but it ties up logical resources like goroutine stacks and potentially other dependent tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Non-blocking Alternatives
&lt;/h3&gt;

&lt;p&gt;To avoid blocking reads, you can use non-blocking alternatives like the select statement with a default case. The select statement in Go is a powerful feature that allows a goroutine to wait on multiple communication operations, making it possible to perform non-blocking operations and handle multiple channels. The select statement works by evaluating multiple channel operations and proceeding with the first one that is ready. If multiple operations are ready, one of them is chosen at random. If no operations are ready, the default case, if present, is executed, making it a non-blocking operation. &lt;/p&gt;

&lt;p&gt;The basic syntax of the select statement:&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;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c"&gt;// Do something when ch1 is ready for receiving&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;ch2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c"&gt;// Do something when ch2 is ready for sending&lt;/span&gt;
&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c"&gt;// Do something when no channels are ready (non-blocking path)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code review
&lt;/h3&gt;

&lt;p&gt;As a code reviewer, you must be able to identify this potentially dangerous code, provide a good explanation of how to avoid it and encourage the teammate to fix the problem. To fix the problem let's implement a &lt;code&gt;select&lt;/code&gt; statement. The fix will look like the following:&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;ch&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="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Goroutine to send data to the channel after 2 seconds&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;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sent: 42"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="c"&gt;// Main function performing a non-blocking read&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&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;"Continuing execution..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;default&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"No value received"&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;500&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;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Sleep for a while to prevent busy looping&lt;/span&gt;
            &lt;span class="c"&gt;// handle the execution flow of instructions and operations that must continue&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we run this, we'll see the following behaviour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt;
&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt;
&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt;
&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt;
&lt;span class="n"&gt;Received&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;Continuing&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;2.31&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; function will repeatedly print “No data received” during the times when the channel is empty, interspersed with “Received: 42” as values become available. The default case ensures the main function does not block and can perform other operations (like printing “No data received” and sleeping). This mechanism ensures that the main function remains responsive, even if one or both channels do not have data available.&lt;/p&gt;

&lt;p&gt;It's that easy!&lt;/p&gt;

</description>
      <category>go</category>
      <category>interview</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Tricky Golang interview questions - Part 5: interface == nil</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Wed, 26 Jun 2024 14:09:30 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-5-interface-nil-2agh</link>
      <guid>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-5-interface-nil-2agh</guid>
      <description>&lt;p&gt;Another topic I would like to discuss in these series is the interface to nil comparison problem. This question is frequently asked during many golang interviews and requires an understanding of how types are constructed under the hood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question: Which &lt;code&gt;if&lt;/code&gt; statements will be evaluated as &lt;code&gt;true&lt;/code&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="s"&gt;"fmt"&lt;/span&gt;  

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SomeType&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SomeImpl&lt;/span&gt; &lt;span class="k"&gt;struct&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="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;SomeImpl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Get&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="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;aType&lt;/span&gt; &lt;span class="n"&gt;SomeType&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;aType&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;"nil interface"&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;aImpl&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SomeImpl&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;aImpl&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;"nil struct"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="n"&gt;aType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aImpl&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;aType&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;"nil assignment"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we all know (hope so) the empty interface in golang holds a &lt;code&gt;nil&lt;/code&gt; value. The default value of an empty interface is &lt;strong&gt;nil&lt;/strong&gt;. This means the uninitialised variable &lt;code&gt;var aType SomeType&lt;/code&gt; holds a &lt;code&gt;nil&lt;/code&gt; value because it has a type of empty (nil) interface. In this case, the if condition is fulfilled, we will see a print statement in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good, let's continue further. &lt;br&gt;
We have another uninitialised variable &lt;code&gt;var aImpl *SomeImpl&lt;/code&gt; which is a pointer to the struct. As you know in golang &lt;strong&gt;all memory is initialised (zeroed)&lt;/strong&gt; this means that the pointers, even if they are uninitialised, will have a default value, which is &lt;code&gt;nil&lt;/code&gt;. So we have one more fulfilled if condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;
&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the last, we see a value assignment (value initialisation) of a struct pointer value to the interface variable &lt;code&gt;aType = aImpl&lt;/code&gt;. Judging by the earlier made statements it is logical to assume that we assign a &lt;code&gt;nil&lt;/code&gt; value to the &lt;code&gt;var aType&lt;/code&gt; and in the result, &lt;code&gt;aType&lt;/code&gt; will remain &lt;code&gt;nil&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;
&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;
&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="n"&gt;assignment&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.318&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sounds logical, so the confident answer is:&lt;br&gt;
&lt;strong&gt;The program will output all print statements into the terminal because all if statements will be fulfilled during the execution!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Okay, that sounds good (would say the interviewer). Let's run the program and check the results. The actual result looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;
&lt;span class="no"&gt;nil&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;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.318&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you already noticed, the output does not contain the last &lt;code&gt;nil assignment&lt;/code&gt; print statement. So, why this happened?&lt;br&gt;
To answer this question we must dig deeper into the language to understand how interfaces are constructed in golang.&lt;/p&gt;
&lt;h4&gt;
  
  
  Interface
&lt;/h4&gt;

&lt;p&gt;In golang, an interface is a type that specifies a set of method signatures. When a value is assigned to an interface, golang constructs an interface value that consists of two parts: &lt;strong&gt;the dynamic type and the dynamic value&lt;/strong&gt;. This is commonly referred to as the “interface tuple.”&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Type&lt;/strong&gt;: This is a pointer to a type descriptor that describes the type of the concrete value stored in the interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Value&lt;/strong&gt;: This is a pointer to the actual value that the interface holds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The interface tuple can be represented as the following structs:&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;iface&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;tab&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;itab&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;itab&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;inter&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;interfacetype&lt;/span&gt;
    &lt;span class="n"&gt;_type&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;_type&lt;/span&gt;
    &lt;span class="n"&gt;hash&lt;/span&gt;  &lt;span class="kt"&gt;uint32&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;
    &lt;span class="n"&gt;fun&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="kt"&gt;uintptr&lt;/span&gt;  &lt;span class="c"&gt;// variable sized, actually [n]uintptr&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tab&lt;/code&gt;: A pointer to an &lt;code&gt;itab&lt;/code&gt; structure that contains information about the type and the methods that the type implements for the interface.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt;: A pointer to the actual data held by the interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a value is assigned to an interface, golang finds the type descriptor for the concrete type being assigned to the interface. Then sets up the method table (&lt;code&gt;itab&lt;/code&gt;) that allows method calls through the interface to be dispatched to the correct implementation and finally stores a pointer to the actual value in the data field of the interface.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;aType = aImpl&lt;/code&gt; is executed &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Determining Interface Implementation&lt;/strong&gt;: golang first determines that &lt;code&gt;*SomeImpl&lt;/code&gt; (a pointer to &lt;code&gt;SomeImpl&lt;/code&gt;) implements the &lt;code&gt;SomeType&lt;/code&gt; interface because &lt;code&gt;*SomeImpl&lt;/code&gt; has a method &lt;code&gt;Get()&lt;/code&gt; with the correct signature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Looking Up the Type Descriptor&lt;/strong&gt;: golang looks up the type descriptor for &lt;code&gt;*SomeImpl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creating the&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;itab&lt;/code&gt;&lt;/strong&gt;: golang creates an &lt;code&gt;itab&lt;/code&gt; structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assigning the Pointer&lt;/strong&gt;: golang assigns the pointer to the &lt;code&gt;SomeImpl&lt;/code&gt; value to the data field of the interface.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface (aType)
+------------+           +-----------+
| tab        |----------&amp;gt;|  itab     |
|            |           |-----------|
| data       |--+        |  inter    |
+------------+  |        |  _type    |
                |        |  fun[0]   |
                |        +-----------+
                |
                v
         +---------------+
         |   *SomeImpl   |
         +---------------+
         |   ........    |
         +---------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;To sum up, what we learned, the previous explanation in short means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+ uninitialised +-------------+ initialised +

interface (aType)             interface (aType)
+------------+                +--------------------------------+
| tab:  nil  |                | tab:  type of *SomeImpl        |
| data: nil  |                | data: value of *SomeImpl (nil) |
+------------+                +--------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the tricky part. &lt;br&gt;
In golang when checking if an &lt;code&gt;interface&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;, both the &lt;code&gt;tab&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; fields must be &lt;code&gt;nil&lt;/code&gt;. &lt;strong&gt;If an &lt;code&gt;interface&lt;/code&gt; holds a &lt;code&gt;nil&lt;/code&gt; pointer of a concrete type, the &lt;code&gt;tab&lt;/code&gt; field will not be &lt;code&gt;nil&lt;/code&gt;, so the &lt;code&gt;interface&lt;/code&gt; itself will not be considered &lt;code&gt;nil&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the reason why we don't see the last print statement inside the terminal. After execution of &lt;code&gt;aType = aImpl&lt;/code&gt; the variable &lt;code&gt;aType&lt;/code&gt; is no longer considered as a nil / empty interface.&lt;/p&gt;

&lt;p&gt;It's that easy!&lt;/p&gt;

</description>
      <category>go</category>
      <category>interview</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Tricky Golang interview questions - Part 4: Concurrent Consumption</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Mon, 24 Jun 2024 15:28:39 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-4-concurrent-consumption-34oe</link>
      <guid>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-4-concurrent-consumption-34oe</guid>
      <description>&lt;p&gt;I want to discuss an example that is very interesting. I was surprised that many experienced developers were unable to answer it correctly. This example involves buffered channels and concurrency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question: What will happen when we run this code?&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;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;ch&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="k"&gt;chan&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;4&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;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
        &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
        &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's analyse this piece of code. What we have here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a buffered channel ch of type int with a capacity of 4 is created&lt;/li&gt;
&lt;li&gt;a goroutine that sends values&lt;/li&gt;
&lt;li&gt;a goroutine sends five values to the channel&lt;/li&gt;
&lt;li&gt;the first 4 sends will fill the channel&lt;/li&gt;
&lt;li&gt;the fifth send operation will be blocked because the channel is at capacity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This idea seems straightforward, and you give the interviewer a confident answer: &lt;strong&gt;Since the buffer capacity is only 4, the fifth send operation will block, causing a deadlock. Channels in go block when they are full and more values are being sent.&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="n"&gt;fatal&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;goroutines&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;asleep&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;deadlock&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the interviewer will kindly ask you to run the code and check the results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="m"&gt;5&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.318&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And surprise surprise we see that this code actually works without deadlocks. Many interviewees, even those with significant experience, struggle to explain this unusual behaviour. There must be a deadlock in this code!&lt;/p&gt;

&lt;p&gt;This raises another question: What can you change to create a deadlock in this code? It's quite simple: just remove the anonymous goroutine and send integers into the channel directly within the &lt;code&gt;main&lt;/code&gt; 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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ch&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="k"&gt;chan&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="c"&gt;// deadlock at line:12&lt;/span&gt;
    &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we've created a deadlock:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="n"&gt;fatal&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;goroutines&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;asleep&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;deadlock&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

&lt;span class="n"&gt;goroutine&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;chan&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0x78&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.318&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me explain why this is happening. Why does introducing a simple anonymous goroutine fix the problem?  &lt;/p&gt;

&lt;p&gt;Let's first define how concurrency works in go and what are channels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concurrency in Go is built around goroutines and channels, which provide a simple and powerful model for concurrent programming. &lt;/li&gt;
&lt;li&gt;A goroutine is a lightweight thread managed by the Go runtime. Goroutines are created using the go keyword followed by a function call. &lt;/li&gt;
&lt;li&gt;Channels provide a way for goroutines to communicate with each other and synchronize their execution. Channels can be used to send and receive values between goroutines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Channels can be buffered or unbuffered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unbuffered channels&lt;/strong&gt; have a capacity of 0. When a sender sends a value on an unbuffered channel, it will block until a receiver is ready to receive the value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffered channels&lt;/strong&gt; have a capacity greater than 0. When a sender sends a value on a buffered channel, it will only block if the buffer is full.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we understand how concurrency works in Go, let’s explore an important concept related to channels.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrent Consumption
&lt;/h3&gt;

&lt;p&gt;The main idea behind concurrent consumption is to ensure that values sent to a channel are being read (or consumed) while they are being sent. This prevents the channel from getting full and blocking further send operations. Concurrent consumption in Go involves having one or more goroutines that send data to a channel while one or more other goroutines read from the same channel. This pattern is commonly used to handle situations where production (sending data) and consumption (receiving data) happen at different rates.&lt;/p&gt;

&lt;p&gt;To ensure a smooth concurrent flow in this scenario, we need to clearly define producers and consumers that run concurrently. In go, the &lt;code&gt;main&lt;/code&gt; function starts executing immediately upon the program's start, in its own goroutine.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the example with a deadlock, there's a single goroutine that acts as both &lt;strong&gt;the producer and consumer&lt;/strong&gt;. This means that within the same goroutine, values are being sent into a channel and simultaneously received from it. However, the deadlock occurs because the channel is filled with values before all it gets consumed. This results in a situation where the channel becomes blocked, preventing further operations.&lt;/li&gt;
&lt;li&gt;In the first example the &lt;strong&gt;the producer and consumer are separated&lt;/strong&gt;, they run in different goroutines. By using an anonymous goroutine to send values, the &lt;code&gt;main&lt;/code&gt; function is free to read from the channel concurrently. This prevents the channel from getting full and blocking further sends, avoiding a deadlock situation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the correct answer is:&lt;br&gt;
&lt;strong&gt;The program will output all values that were sent into the buffered channel.&lt;/strong&gt;&lt;br&gt;
Why? &lt;br&gt;
&lt;strong&gt;Because we have 2 goroutines one to produce data (anonymous) and another to consume (main). This way we ensure a flawless execution that empties the channel on time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's that easy!&lt;/p&gt;

</description>
      <category>interview</category>
      <category>go</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Tricky Golang interview questions - Part 3: nil receivers</title>
      <dc:creator>Harutyun Mardirossian</dc:creator>
      <pubDate>Fri, 31 May 2024 17:04:28 +0000</pubDate>
      <link>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-3-nil-receivers-5740</link>
      <guid>https://forem.com/crusty0gphr/tricky-golang-interview-questions-part-3-nil-receivers-5740</guid>
      <description>&lt;p&gt;I have one more tricky interview question to discuss in this series. This one is related to function receivers and methods in golang, often called nil receivers. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question: What is the output of the following?&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;gopher&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;print&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;"gopher-printer works!"&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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gpr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;
    &lt;span class="n"&gt;gpr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;print&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;A quick note here, this question has one of the highest failing rates when asked during the interviews.  Most of the interviewees never tried or never experienced such behaviour.&lt;/p&gt;

&lt;h4&gt;
  
  
  Receiver
&lt;/h4&gt;

&lt;p&gt;A receiver argument is what distinguishes a method from a regular function in GoLang. In essence, a method is simply a function that includes a receiver argument. A receiver can also be of a non-struct type. For example, in the code below, we have a method &lt;code&gt;add()&lt;/code&gt; with a receiver of type &lt;code&gt;Integer&lt;/code&gt;, which is an alias for &lt;code&gt;int&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;type&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Integer&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;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, that's a pretty straightforward representation of what a receiver is. Now, let's try answering this question. If you come from OOP languages like Java, C# or C++ you are familiar with the term &lt;code&gt;null pointer exception&lt;/code&gt;.  It means that &lt;strong&gt;you are trying to access a part of something that doesn't exist&lt;/strong&gt;. Here's the classic example from Java:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NullPointer&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trying to compile this will throw the &lt;code&gt;null pointer exception&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Exception &lt;span class="k"&gt;in &lt;/span&gt;thread &lt;span class="s2"&gt;"main"&lt;/span&gt; java.lang.NullPointerException
        at NullPointer-main &lt;span class="o"&gt;(&lt;/span&gt;NullPointer.java:7&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The developer familiar with this concept will shortly answer:&lt;br&gt;
&lt;strong&gt;The program will panic with nil pointer dereference if we try to run this.&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="nb"&gt;panic&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;invalid&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="n"&gt;pointer&lt;/span&gt; &lt;span class="n"&gt;dereference&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's actually run the program and make sure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="n"&gt;gopher&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;printer&lt;/span&gt; &lt;span class="n"&gt;works&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.318&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, most interviewees get confused by this behaviour and assume that the Go compiler initialises the struct when we create the variable with the type &lt;code&gt;var gpr *gopher&lt;/code&gt;. To test this let's add a print line inside the &lt;code&gt;print()&lt;/code&gt; function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;print&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;"receiver: %v &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;r&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;"gopher-printer works!"&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;and build the program again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;gopher&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;printer&lt;/span&gt; &lt;span class="n"&gt;works&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.318&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oops, the struct is not initialised, its value is &lt;code&gt;nil&lt;/code&gt;. Again, if you come from OOP languages this may seem like a static method call, but it's far different from that concept. You see, receivers in Go act like a basic argument, and in this case, when we call a method on an uninitialised struct, inside the methods &lt;code&gt;nil&lt;/code&gt; has passed as a receiver as if you do something like this instead:&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;gopher&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&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;"gopher-printer works!"&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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gpr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The nil receiver is just a parameter.&lt;/p&gt;

&lt;p&gt;After we clear this out, you give a confident answer to the interviewer:&lt;br&gt;
&lt;strong&gt;This will print a message "gopher-printer works!" into the console and will not cause a compile time panic&lt;/strong&gt;&lt;br&gt;
It's that easy!&lt;/p&gt;

&lt;p&gt;Here some interviewers like to ask the following:&lt;br&gt;
&lt;strong&gt;What will cause the program to panic?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer is very simple. Since the nil receiver is just a parameter, this panic will only occur if the method tries to access the struct fields, such as &lt;code&gt;name&lt;/code&gt; in our case.&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;gopher&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// &amp;lt;-- accessing the field&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;"gopher-printer works!"&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;So the full answer to this tricky question is:&lt;br&gt;
&lt;strong&gt;When you call this method from a nil pointer you will not get any compiler errors but you may get runtime panic if the method tries to access the struct fields.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Bonus section
&lt;/h3&gt;

&lt;p&gt;Another interesting point to note is that a nil receiver can be initialized inside the method. However, this initialization has no effect outside of that method. Check the following code, I initialise the receiver inside the method:&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;gopher&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// init the receiver with a new struct and populate the field&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"crusty0gphr"&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;"hi there %s &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;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gpr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gopher&lt;/span&gt;
    &lt;span class="n"&gt;gpr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this program will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s"&gt;"main.go"&lt;/span&gt;

&lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="n"&gt;there&lt;/span&gt; &lt;span class="n"&gt;crusty0gphr&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;exited&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;code&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;in&lt;/span&gt; &lt;span class="m"&gt;0.318&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But inside the &lt;code&gt;main&lt;/code&gt; function, the variable &lt;code&gt;gpr&lt;/code&gt; will remain &lt;code&gt;nil&lt;/code&gt; and accessing its field will cause a compile time panic!&lt;br&gt;
Now, It's that easy, finally!&lt;/p&gt;

</description>
      <category>go</category>
      <category>interview</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
