<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nicolas Lepage</title>
    <description>The latest articles on DEV Community by Nicolas Lepage (@nlepage).</description>
    <link>https://dev.to/nlepage</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%2F170792%2Ff7b3b62a-4900-4579-925a-2bc65de53987.jpeg</url>
      <title>DEV Community: Nicolas Lepage</title>
      <link>https://dev.to/nlepage</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nlepage"/>
    <language>en</language>
    <item>
      <title>Testing Go WebAssembly code on Github actions</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Fri, 20 Aug 2021 22:29:11 +0000</pubDate>
      <link>https://dev.to/nlepage/testing-go-webassembly-code-on-github-actions-j81</link>
      <guid>https://dev.to/nlepage/testing-go-webassembly-code-on-github-actions-j81</guid>
      <description>&lt;p&gt;This small post will run you through how to setup Github actions to run tests for Go code targeting WebAssembly.&lt;/p&gt;

&lt;p&gt;OK, take me straight to the complete setup!&lt;/p&gt;

&lt;p&gt;Here is the most &lt;a href="https://github.com/actions/starter-workflows/blob/main/ci/go.yml"&gt;basic configuration suggested by Github for Go repositories&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Go&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Go&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.17&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go build -v ./...&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go test -v ./...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing we need is to tell the &lt;code&gt;go&lt;/code&gt; command we want to target WebAssembly, which can be done declaring the &lt;code&gt;GOOS&lt;/code&gt; and &lt;code&gt;GOARCH&lt;/code&gt; variables on the job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GOOS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;js&lt;/span&gt;
      &lt;span class="na"&gt;GOARCH&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wasm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "Build" step should now work as expected, checking that our code compiles to WebAssembly.&lt;/p&gt;

&lt;p&gt;However for the "Test" step to work, we need some more configuration.&lt;/p&gt;

&lt;p&gt;Of course we need an execution environment for our compiled WebAssembly, in our case Node.js will be perfect, so let's set it up in addition of Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Node.js&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2.4.0&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally we need to add &lt;code&gt;go_js_wasm_exec&lt;/code&gt; to our &lt;code&gt;PATH&lt;/code&gt; to enable &lt;code&gt;go test&lt;/code&gt; running our tests using Node.js.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;go_js_wasm_exec&lt;/code&gt; is located in the &lt;code&gt;misc/wasm&lt;/code&gt; directory of the Go installation, we can add it to the &lt;code&gt;PATH&lt;/code&gt; with a simple step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup PATH for wasm&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "${{env.GOROOT}}/misc/wasm" &amp;gt;&amp;gt; $GITHUB_PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Go&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GOOS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;js&lt;/span&gt;
      &lt;span class="na"&gt;GOARCH&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wasm&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Go&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.17&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup PATH for wasm&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "${{env.GOROOT}}/misc/wasm" &amp;gt;&amp;gt; $GITHUB_PATH&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Node.js&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2.4.0&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go build -v ./...&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go test -v ./...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup is based on &lt;a href="https://github.com/golang/go/wiki/WebAssembly#executing-webassembly-with-nodejs"&gt;the instructions in the Go WebAssembly wiki page&lt;/a&gt;, it can be adapted to run tests in a browser.&lt;/p&gt;

</description>
      <category>github</category>
      <category>go</category>
      <category>webassembly</category>
      <category>testing</category>
    </item>
    <item>
      <title>Gopher drawings!</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Tue, 27 Jul 2021 07:51:59 +0000</pubDate>
      <link>https://dev.to/nlepage/gopher-drawings-294i</link>
      <guid>https://dev.to/nlepage/gopher-drawings-294i</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nlepage"&gt;
        nlepage
      &lt;/a&gt; / &lt;a href="https://github.com/nlepage/gophers"&gt;
        gophers
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Some gophers 🐻
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Gophers 🐻
&lt;/h1&gt;
&lt;p&gt;Hey 👋! Here are some drawings I have been using for &lt;a href="https://talks.lepage.dev" rel="nofollow"&gt;talks about Golang&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are mainly &lt;a href="https://raw.githubusercontent.com/nlepage/gophers/main/#gophers"&gt;gophers&lt;/a&gt;, but also some &lt;a href="https://raw.githubusercontent.com/nlepage/gophers/main/#dukes"&gt;dukes&lt;/a&gt;, and &lt;a href="https://raw.githubusercontent.com/nlepage/gophers/main/#miscellaneous"&gt;miscellaneous&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gophers drawings are based on the original design of the Go gopher by &lt;a href="http://reneefrench.blogspot.com/" rel="nofollow"&gt;Renee French&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See &lt;a href="https://raw.githubusercontent.com/nlepage/gophers/main/#license"&gt;License&lt;/a&gt; for license information.&lt;/p&gt;
&lt;h2&gt;
Gophers&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/alien_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H8QP5EgR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/alien_gopher.png" alt="alien_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/asleep_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sYs1ZOS7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/asleep_1.png" alt="asleep_1.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/asleep_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iMBdd16a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/asleep_2.png" alt="asleep_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/backface_seating_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TeguSZ9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/backface_seating_gopher.png" alt="backface_seating_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/backface_seating_gopher_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zmMgxyU8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/backface_seating_gopher_2.png" alt="backface_seating_gopher_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/candy_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tRZ4oux2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/candy_gopher.png" alt="candy_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/candy_gopher_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bA30MTym--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/candy_gopher_2.png" alt="candy_gopher_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/candy_gopher_3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KmAWTnTP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/candy_gopher_3.png" alt="candy_gopher_3.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/charlie_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vvEo0aBE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/charlie_gopher.png" alt="charlie_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/chasing_gophers.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tvKgSYAf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/chasing_gophers.png" alt="chasing_gophers.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/crying_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VLAWmQ3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/crying_gopher.png" alt="crying_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/dammy_gopher_facing_left.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9P7WYCvR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/dammy_gopher_facing_left.png" alt="dammy_gopher_facing_left.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/dead_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rszcuJtH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/dead_gopher.png" alt="dead_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/dr_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n51a-fyD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/dr_gopher.png" alt="dr_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/experiment_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_0v1xKYD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/experiment_1.png" alt="experiment_1.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/experiment_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6bRpyVqE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/experiment_2.png" alt="experiment_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/experiment_3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QaR-78gH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/experiment_3.png" alt="experiment_3.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/experiment_4.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9KKRXk-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/experiment_4.png" alt="experiment_4.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/facing_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xcvyy7iR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/facing_gopher.png" alt="facing_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_blue.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nYNMgEXj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_blue.png" alt="gopher_blue.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_brush.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---RNZNayv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_brush.png" alt="gopher_brush.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_chief.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UzyInf-9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_chief.png" alt="gopher_chief.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_chief_handraised.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WGifZaT2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_chief_handraised.png" alt="gopher_chief_handraised.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_chief_saying.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nF0huT61--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_chief_saying.png" alt="gopher_chief_saying.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_chief_shouting.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k2y4gimA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_chief_shouting.png" alt="gopher_chief_shouting.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_facing_back.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kmWcBW-O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_facing_back.png" alt="gopher_facing_back.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_heart_running_blue.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YKW1u2SQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_heart_running_blue.png" alt="gopher_heart_running_blue.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_heart_running_pink.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5WnZvyJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_heart_running_pink.png" alt="gopher_heart_running_pink.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_heart_running_purple.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--siXVTkye--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_heart_running_purple.png" alt="gopher_heart_running_purple.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_heart_running_yellow.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N1lgQ5F2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_heart_running_yellow.png" alt="gopher_heart_running_yellow.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_purple.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lXHk25Vs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_purple.png" alt="gopher_purple.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_saying_go.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QyreWAai--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_saying_go.png" alt="gopher_saying_go.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_star.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bb0vOMfG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_star.png" alt="gopher_star.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/gopher_yellow.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jfpfV8Rt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/gopher_yellow.png" alt="gopher_yellow.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/goroutine.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g0IGzMwo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/goroutine.png" alt="goroutine.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/goroutine_facing_side.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9PAV0gT8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/goroutine_facing_side.png" alt="goroutine_facing_side.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/goroutine_wings.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DVEagLEJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/goroutine_wings.png" alt="goroutine_wings.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/hang_glider_gopher_purple.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uqv8HRHo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/hang_glider_gopher_purple.png" alt="hang_glider_gopher_purple.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/heart_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TZH_T3Wh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/heart_gopher.png" alt="heart_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/heart_gopher_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DulH1RMs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/heart_gopher_2.png" alt="heart_gopher_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/hodor_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kkjMzj_E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/hodor_gopher.png" alt="hodor_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/jugsummercamp_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ENYAqgUU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/jugsummercamp_gopher.png" alt="jugsummercamp_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/kite_gopher_yellow.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TNXbdbMI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/kite_gopher_yellow.png" alt="kite_gopher_yellow.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/large_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SNQkJpAR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/large_gopher.png" alt="large_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/laying_down_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3gywYPm9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/laying_down_gopher.png" alt="laying_down_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_backpack.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8D6fxZbS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_backpack.png" alt="little_gopher_backpack.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_byebye.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GgOfdrFu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_byebye.png" alt="little_gopher_byebye.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_crying.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jqrVECjU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_crying.png" alt="little_gopher_crying.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_facing_backleft.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--frllsOXa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_facing_backleft.png" alt="little_gopher_facing_backleft.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_facing_front.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zKHhZ7S9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_facing_front.png" alt="little_gopher_facing_front.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_facing_right.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GUsOlygx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_facing_right.png" alt="little_gopher_facing_right.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_facing_right_diapers.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ccDyBm7G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_facing_right_diapers.png" alt="little_gopher_facing_right_diapers.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_heart.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HCMfAW_s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_heart.png" alt="little_gopher_heart.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_pushing.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CnxMKO7k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_pushing.png" alt="little_gopher_pushing.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/little_gopher_shouting.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g5K9NnaC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/little_gopher_shouting.png" alt="little_gopher_shouting.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/nico_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MHpHwQNJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/nico_gopher.png" alt="nico_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/old_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mJgmHeWu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/old_gopher.png" alt="old_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/old_gopher_crying.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YZzP-TAC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/old_gopher_crying.png" alt="old_gopher_crying.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/old_gopher_shouting.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DehImu5b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/old_gopher_shouting.png" alt="old_gopher_shouting.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/scheduler.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V5SY-YDS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/scheduler.png" alt="scheduler.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/scheduler_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qwpBfGhR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/scheduler_2.png" alt="scheduler_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/scheduler_open_mouth.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e95ZsBJX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/scheduler_open_mouth.png" alt="scheduler_open_mouth.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/scooter_gopher_blue.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ckAJgzIU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/scooter_gopher_blue.png" alt="scooter_gopher_blue.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/seating_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cxMaNEXG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/seating_gopher.png" alt="seating_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/sitting_backface.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aH12NeYG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/sitting_backface.png" alt="sitting_backface.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/slide_gopher_blue.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LddqBAF1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/slide_gopher_blue.png" alt="slide_gopher_blue.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/small_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i4BnwhEs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/small_gopher.png" alt="small_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/space_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BysjVQVj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/space_gopher.png" alt="space_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/swing_gophers.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2GOZZPnm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/swing_gophers.png" alt="swing_gophers.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/trampoline_gopher_pink.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r1a7e_kn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/trampoline_gopher_pink.png" alt="trampoline_gopher_pink.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/waving_gopher_blue.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AJVBqqni--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/waving_gopher_blue.png" alt="waving_gopher_blue.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/gophers/waving_gopher_pink.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--shsY6l6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/gophers/waving_gopher_pink.png" alt="waving_gopher_pink.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Dukes&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/baby_duke.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LOTXzwn0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/baby_duke.png" alt="baby_duke.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/candy_duke.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mwfzCfp5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/candy_duke.png" alt="candy_duke.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/duke_handraised.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U1iDPPii--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/duke_handraised.png" alt="duke_handraised.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/duke_jumping.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4JW3iA8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/duke_jumping.png" alt="duke_jumping.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/duke_kite.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2dpQQaiR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/duke_kite.png" alt="duke_kite.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/duke_laying_down.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4isOzZIx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/duke_laying_down.png" alt="duke_laying_down.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/duke_sitting.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VoFZjasn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/duke_sitting.png" alt="duke_sitting.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/facing_duke.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A0suauGq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/facing_duke.png" alt="facing_duke.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/thread.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W0YFd9eP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/thread.png" alt="thread.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/thread_facing_side.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jIi9tNYl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/thread_facing_side.png" alt="thread_facing_side.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/dukes/waving_duke.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WMngalJw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/dukes/waving_duke.png" alt="waving_duke.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Miscellaneous&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/CPU.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wTzwNLds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/CPU.png" alt="CPU.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/CPU_facing_side.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XKSykyIg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/CPU_facing_side.png" alt="CPU_facing_side.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/backpack.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tbb8xZ6O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/backpack.png" alt="backpack.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/bubble.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0c19nA-n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/bubble.png" alt="bubble.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/buffered_channel.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gzlMgccp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/buffered_channel.png" alt="buffered_channel.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/candy_box.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NjzbcW3j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/candy_box.png" alt="candy_box.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/candy_channel.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBSkDVrE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/candy_channel.png" alt="candy_channel.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/candy_tree.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6y5FsWSh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/candy_tree.png" alt="candy_tree.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/closed_egg.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2PfwMW-b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/closed_egg.png" alt="closed_egg.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/cloud1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ltmxHvR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/cloud1.png" alt="cloud1.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/cloud2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IOg1ZNfW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/cloud2.png" alt="cloud2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/cloud3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vpvabjOV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/cloud3.png" alt="cloud3.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/cloud4.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MUrTGuE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/cloud4.png" alt="cloud4.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/cloud5.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GD2wodOb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/cloud5.png" alt="cloud5.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/cpu_facing.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wrPUeZAV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/cpu_facing.png" alt="cpu_facing.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/cpu_side.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G0Je5K4E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/cpu_side.png" alt="cpu_side.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/fire.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xuTh5BL_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/fire.png" alt="fire.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R8kkQUIo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_1.png" alt="heart_1.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SxMxzgSY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_2.png" alt="heart_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vUgmp85r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_3.png" alt="heart_3.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_4.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ddj-gDrf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_4.png" alt="heart_4.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_b_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8XZ8-EzB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_b_1.png" alt="heart_b_1.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_b_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpVjGPUA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_b_2.png" alt="heart_b_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_channel.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kVYCxffN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_channel.png" alt="heart_channel.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_channel_bicolor.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JUJI6uew--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_channel_bicolor.png" alt="heart_channel_bicolor.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_channel_blue.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f6FHM-9b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_channel_blue.png" alt="heart_channel_blue.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_channel_green.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aaeYPN05--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_channel_green.png" alt="heart_channel_green.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_g_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wLW37-r4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_g_1.png" alt="heart_g_1.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_g_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ycn4llAR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_g_2.png" alt="heart_g_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heart_tree.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M59bR7ZE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heart_tree.png" alt="heart_tree.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/heavy.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oZF9WUQ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/heavy.png" alt="heavy.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/hug.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BWmD8n8e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/hug.png" alt="hug.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/large_bubble.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a2VLi5o5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/large_bubble.png" alt="large_bubble.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/lock.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SxYSnTjk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/lock.png" alt="lock.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/medium_bubble.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fQ1g48SA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/medium_bubble.png" alt="medium_bubble.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/milk_bottle.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VvQ0Fx4k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/milk_bottle.png" alt="milk_bottle.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/opened_egg.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gExdRldF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/opened_egg.png" alt="opened_egg.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/opened_egg_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wm6QR0L2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/opened_egg_gopher.png" alt="opened_egg_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/paint_bucket_blue.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hDZ3LrJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/paint_bucket_blue.png" alt="paint_bucket_blue.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/paint_bucket_green.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qfhMzxxl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/paint_bucket_green.png" alt="paint_bucket_green.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/pram.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qxEqDGfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/pram.png" alt="pram.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/pushpin.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JZOkhjlo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/pushpin.png" alt="pushpin.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/scalpel.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f-4u6PMQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/scalpel.png" alt="scalpel.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/small_bubble.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IXdi7M7w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/small_bubble.png" alt="small_bubble.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/sparadra.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EV1CFrj7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/sparadra.png" alt="sparadra.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/sun.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7clZOj3Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/sun.png" alt="sun.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/sweat_drop.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d-sG76PF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/sweat_drop.png" alt="sweat_drop.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/sweat_drop_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3TYFJsNn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/sweat_drop_2.png" alt="sweat_drop_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/thug_glasses.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kcvjOgv_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/thug_glasses.png" alt="thug_glasses.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/misc/waitgroup.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1fSvrDQv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/misc/waitgroup.png" alt="waitgroup.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Uncolored&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/buffered_channel.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mw4hfv01--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/buffered_channel.png" alt="buffered_channel.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/candy_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ABQXKU_T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/candy_gopher.png" alt="candy_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/facing_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VySi8174--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/facing_gopher.png" alt="facing_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/gopher_brush.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eLDhI0PK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/gopher_brush.png" alt="gopher_brush.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/gopher_facing_back.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--42CNnsJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/gopher_facing_back.png" alt="gopher_facing_back.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/gopher_facing_right.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rW01cse3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/gopher_facing_right.png" alt="gopher_facing_right.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/gopher_heart_running.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MJD1TqJB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/gopher_heart_running.png" alt="gopher_heart_running.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/gopher_pushing.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZGSWDPaZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/gopher_pushing.png" alt="gopher_pushing.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/gopher_star.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lR9f-iCM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/gopher_star.png" alt="gopher_star.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kof1Jpjs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_1.png" alt="heart_1.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KTHIC9WM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_2.png" alt="heart_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n56BWEu3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_3.png" alt="heart_3.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_4.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mmiMwALK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_4.png" alt="heart_4.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_channel.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9idhngcc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_channel.png" alt="heart_channel.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_channel_bicolor.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VBrqN0C_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_channel_bicolor.png" alt="heart_channel_bicolor.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_gopher.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8hPRtoq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_gopher.png" alt="heart_gopher.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/heart_gopher_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IA3u-6iC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/heart_gopher_2.png" alt="heart_gopher_2.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/paint_bucket.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--07u3QfVN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/paint_bucket.png" alt="paint_bucket.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/paint_bucket_brush.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4QJ5R8Tk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/paint_bucket_brush.png" alt="paint_bucket_brush.png"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nlepage/gophers/blob/main/uncolored/scheduler.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rj5v1EM_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/nlepage/gophers/main/thumbnails/uncolored/scheduler.png" alt="scheduler.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
License&lt;/h2&gt;
&lt;p&gt;Original design of the Go gopher by &lt;a href="http://reneefrench.blogspot.com/" rel="nofollow"&gt;Renee French&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gophers © 2021 by Nicolas Lepage is licensed under Attribution-NonCommercial-ShareAlike 4.0 International.
To view a copy of this license, visit &lt;a href="http://creativecommons.org/licenses/by-nc-sa/4.0/" rel="nofollow"&gt;http://creativecommons.org/licenses/by-nc-sa/4.0/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nlepage/gophers"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>go</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Emulate a Go HTTP server in your browser</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Wed, 10 Feb 2021 11:30:20 +0000</pubDate>
      <link>https://dev.to/nlepage/emulate-a-go-http-server-in-your-browser-32</link>
      <guid>https://dev.to/nlepage/emulate-a-go-http-server-in-your-browser-32</guid>
      <description>&lt;p&gt;Hi 👋 I'd like to share &lt;code&gt;github.com/nlepage/go-wasm-http-server&lt;/code&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nlepage" rel="noopener noreferrer"&gt;
        nlepage
      &lt;/a&gt; / &lt;a href="https://github.com/nlepage/go-wasm-http-server" rel="noopener noreferrer"&gt;
        go-wasm-http-server
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Embed your Go HTTP handlers in a ServiceWorker and emulate an HTTP server!
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Welcome to go-wasm-http-server 👋&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;
  &lt;a href="https://pkg.go.dev/github.com/nlepage/go-wasm-http-server#section-documentation" rel="nofollow noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/16536ffb673951c652dc63c76c8cb7895d9c600e261642187963f9a3cbe6e987/68747470733a2f2f706b672e676f2e6465762f62616467652f6769746875622e636f6d2f6e6c65706167652f676f2d7761736d2d687474702d7365727665722e737667" alt="Go Reference"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/nlepage/go-wasm-http-server/blob/master/LICENSE" rel="noopener noreferrer"&gt;
    &lt;img alt="License: Apache 2.0" src="https://camo.githubusercontent.com/5f48698f8fcdf403b963b3aac4b43c1d30bad0f6f18be9a9f41d3ea8c737d088/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4170616368652d2d322e302d79656c6c6f772e737667"&gt;
  &lt;/a&gt;
  &lt;a href="https://twitter.com/njblepage" rel="nofollow noopener noreferrer"&gt;
    &lt;img alt="Twitter: njblepage" src="https://camo.githubusercontent.com/95de2185ed10149256f48df26be537f362fb8187d1fb5c6f10b71fdc20b254eb/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6e6a626c65706167652e7376673f7374796c653d736f6369616c"&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Embed your Go HTTP handlers in a ServiceWorker (using &lt;a href="https://mdn.io/WebAssembly/" rel="nofollow noopener noreferrer"&gt;WebAssembly&lt;/a&gt;) and emulate an HTTP server!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Examples&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nlepage.github.io/go-wasm-http-server/hello" rel="nofollow noopener noreferrer"&gt;Hello example&lt;/a&gt; (&lt;a href="https://github.com/nlepage/go-wasm-http-server/tree/master/docs/hello" rel="noopener noreferrer"&gt;sources&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nlepage.github.io/go-wasm-http-server/hello-state" rel="nofollow noopener noreferrer"&gt;Hello example with state&lt;/a&gt; (&lt;a href="https://github.com/nlepage/go-wasm-http-server/tree/master/docs/hello-state" rel="noopener noreferrer"&gt;sources&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nlepage.github.io/go-wasm-http-server/hello-state-keepalive" rel="nofollow noopener noreferrer"&gt;Hello example with state and keepalive&lt;/a&gt; (&lt;a href="https://github.com/nlepage/go-wasm-http-server/tree/master/docs/hello-state-keepalive" rel="noopener noreferrer"&gt;sources&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nlepage.github.io/catption/wasm" rel="nofollow noopener noreferrer"&gt;😺 Catption generator example&lt;/a&gt; (&lt;a href="https://github.com/nlepage/catption/tree/wasm" rel="noopener noreferrer"&gt;sources&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nlepage.github.io/random-password-please/" rel="nofollow noopener noreferrer"&gt;Random password generator web server&lt;/a&gt; (&lt;a href="https://github.com/nlepage/random-password-please" rel="noopener noreferrer"&gt;sources&lt;/a&gt; forked from &lt;a href="https://github.com/jbarham/random-password-please" rel="noopener noreferrer"&gt;jbarham/random-password-please&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How?&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Talk given at the Go devroom of FOSDEM 2021 explaining how &lt;code&gt;go-wasm-http-server&lt;/code&gt; works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/O2RB_8ircdE" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fnlepage%2Fgo-wasm-http-talk%2Fmain%2Fyoutube.png" alt="Deploy a Go HTTP server in your browser Youtube link"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The slides are available &lt;a href="https://nlepage.github.io/go-wasm-http-talk/" rel="nofollow noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why?&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;go-wasm-http-server&lt;/code&gt; can help you put up a demonstration for a project without actually running a Go HTTP server.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Requirements&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;go-wasm-http-server&lt;/code&gt; requires you to build your Go application to WebAssembly, so you need to make sure your code is compatible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no C bindings&lt;/li&gt;
&lt;li&gt;no System dependencies such as file system or network (database server for example)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Step 1: Build to &lt;code&gt;js/wasm&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;In your Go code, replace &lt;a href="https://pkg.go.dev/net/http#ListenAndServe" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;http.ListenAndServe()&lt;/code&gt;&lt;/a&gt; (or &lt;a href="https://pkg.go.dev/net#Listen" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;net.Listen()&lt;/code&gt;&lt;/a&gt;…&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nlepage/go-wasm-http-server" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;This project allows you to build Go HTTP handlers to WebAssembly and embed it in a ServiceWorker to emulate an HTTP server!&lt;/p&gt;

&lt;p&gt;I'd really appreciate to have feedback from people who would give it a try 🙂&lt;/p&gt;

&lt;p&gt;The readme has a usage section and some examples to guide you.&lt;/p&gt;

&lt;p&gt;Here is a video from FOSDEM 21 explaining how this works:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/O2RB_8ircdE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Contributions on the project are more than welcome.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

</description>
      <category>go</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>JS tip: Create debug friendly unique references using String</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Tue, 14 Jan 2020 08:20:41 +0000</pubDate>
      <link>https://dev.to/zenika/js-tip-create-debug-friendly-unique-references-using-string-ifd</link>
      <guid>https://dev.to/zenika/js-tip-create-debug-friendly-unique-references-using-string-ifd</guid>
      <description>&lt;p&gt;Recently I've been facing a case where I needed to create some unique references.&lt;br&gt;
I was creating a JS API and needed to maintain some internal state relative to elements created by the API.&lt;/p&gt;

&lt;p&gt;In practice, I had a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap"&gt;&lt;code&gt;WeakMap&lt;/code&gt;&lt;/a&gt; where I maintained a private state for each public reference returned by the API.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  Why a &lt;code&gt;WeakMap&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;The keys of a &lt;code&gt;WeakMap&lt;/code&gt; are weak references, which means as soon as no one else holds the reference of a key, the key and its value get removed from the map and garbage collected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The type of the public references didn't matter to me, I just needed unique references.&lt;br&gt;
But it would be better if those references were easy to debug, which meant  having at least a relevant &lt;code&gt;toString()&lt;/code&gt; method.&lt;/p&gt;
&lt;h2&gt;
  
  
  ⛔ Non choices ⛔
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;{}&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;What's the easiest way to create a unique reference in JS? Initializing an empty object!&lt;br&gt;
But that doesn't satistfy the "easy to debug" requirement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`debug: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// debug: [object Object]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;String&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A string is easy to debug, you just print it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`ref #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`debug: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// debug: ref #1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But a string isn't a unique reference, anyone may obtain the same reference very easily.&lt;br&gt;
And as a matter of fact, a &lt;code&gt;WeakMap&lt;/code&gt; doesn't accept strings as keys, neither any other primitive type!&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Symbol&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The purpose of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol"&gt;&lt;code&gt;Symbol&lt;/code&gt;&lt;/a&gt; is to create unique references!&lt;br&gt;
There I thought I had my solution...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ref #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`debug: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// TypeError: Cannot convert a Symbol value to a string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wow! Far from what I expected...&lt;br&gt;
Even though &lt;code&gt;Symbol&lt;/code&gt; has a &lt;code&gt;toString()&lt;/code&gt; method, putting it in a string interpolation yells at me!&lt;br&gt;
Furthermore symbols are primitive values, hence &lt;code&gt;WeakMap&lt;/code&gt; won't accept these as keys!&lt;/p&gt;
&lt;h2&gt;
  
  
  🟢 Solutions 🟢
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;class&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There I found myself forced to write my own &lt;code&gt;class&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Ref&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nextId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`ref #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`debug: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// debug: ref #1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is exactly what I wanted, but it feels like I'm squashing a fly with a sledgehammer...&lt;br&gt;
Do I really have to create my own type?&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;new String()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Yes it's possible to use the String constructor, and it is equivalent to using a &lt;code&gt;class&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ref #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`debug: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// debug: ref #1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It does create a unique reference, which isn't of a primitive type.&lt;br&gt;
Hence it may be used as a key for a &lt;code&gt;WeakMap&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn!
&lt;/h2&gt;

&lt;p&gt;Do you have any other ideas? Share them with me!&lt;/p&gt;

&lt;p&gt;Thanks for reading, give a ❤️, leave a comment 💬, and follow me to get notified of my next posts.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Go channels in JS (Bonus 1): nil channel</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Wed, 08 Jan 2020 07:14:54 +0000</pubDate>
      <link>https://dev.to/zenika/go-channels-in-js-bonus-1-nil-channel-b96</link>
      <guid>https://dev.to/zenika/go-channels-in-js-bonus-1-nil-channel-b96</guid>
      <description>&lt;p&gt;This is a bonus post in the "Go channels in JS" series about how I wrote in JavaScript the equivalent of Go(lang) channels.&lt;br&gt;
If you haven't already, I recommend reading at least the first post before reading this one:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/zenika" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1234%2F61529416-7337-4c59-ab27-aaa666d850fc.png" alt="Zenika"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F170792%2Ff7b3b62a-4900-4579-925a-2bc65de53987.jpeg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/zenika/go-channels-in-js-1-5-sending-and-receiving-2lci" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Go channels in JS (1/5): Sending and Receiving&lt;/h2&gt;
      &lt;h3&gt;Nicolas Lepage for Zenika ・ Dec 2 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#go&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;So did you know that Go allows using &lt;code&gt;nil&lt;/code&gt; channels?&lt;br&gt;
Now let's see how and why this is possible.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;nil&lt;/code&gt; channel
&lt;/h2&gt;

&lt;p&gt;Let's start by clarifying what is a &lt;code&gt;nil&lt;/code&gt; channel.&lt;/p&gt;

&lt;p&gt;So far when we wanted to create a channel, we used the &lt;code&gt;make&lt;/code&gt; builtin 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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;make&lt;/code&gt; returns a pointer to a channel, so a &lt;code&gt;nil&lt;/code&gt; channel is just a &lt;code&gt;nil&lt;/code&gt; pointer, in other words no channel at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// This a nil integer channel pointer:&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="c"&gt;// Declared in a more explicit way:&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So why would we need a &lt;code&gt;nil&lt;/code&gt; channel?&lt;/p&gt;

&lt;p&gt;You would think that sending to or receiving from a &lt;code&gt;nil&lt;/code&gt; channel is an illegal operation, but it is actually allowed.&lt;br&gt;
&lt;em&gt;Both will block indefinitely!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now the next question is how is this useful?&lt;br&gt;
We don't want a goroutine to be blocked forever, this is actually a well known problem: a goroutine leak.&lt;/p&gt;

&lt;p&gt;Well there is the &lt;a href="https://tour.golang.org/concurrency/5" rel="noopener noreferrer"&gt;&lt;code&gt;select&lt;/code&gt;&lt;/a&gt; statement we haven't spoken of so far, which allows to wait for several channel operations at the same time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;PrintValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&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="n"&gt;strings&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&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="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;i&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;ints&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received integer: %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;i&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;s&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;strings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received string: %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;s&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if the sender closes the &lt;code&gt;ints&lt;/code&gt; channel?&lt;br&gt;
Receiving from a closed channel returns a &lt;code&gt;nil&lt;/code&gt; value, so &lt;code&gt;PrintValues&lt;/code&gt; will print &lt;code&gt;"Received integer: 0"&lt;/code&gt; on the standard output indefinitely!&lt;/p&gt;

&lt;p&gt;In order to avoid that, it is possible to use a &lt;code&gt;nil&lt;/code&gt; channel to disable one &lt;code&gt;case&lt;/code&gt; of the &lt;code&gt;select&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;PrintValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&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="n"&gt;strings&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&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="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;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&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;ints&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;ints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;nil&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;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;"Received integer: %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;i&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;s&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;strings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received string: %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;s&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As soon as the &lt;code&gt;ints&lt;/code&gt; channel is closed, we replace it by a &lt;code&gt;nil&lt;/code&gt; pointer, which disables the first &lt;code&gt;case&lt;/code&gt; of the &lt;code&gt;select&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of course we have to do the same for the &lt;code&gt;strings&lt;/code&gt; channel, but it would end up blocking the entire &lt;code&gt;select&lt;/code&gt;, and the goroutine executing it...&lt;br&gt;
&lt;code&gt;PrintValues&lt;/code&gt; must return when both channels are closed:&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;PrintValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&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="n"&gt;strings&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&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="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;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&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;ints&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&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;strings&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="n"&gt;ints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;nil&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;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;"Received integer: %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;i&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;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&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;strings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&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;ints&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="n"&gt;strings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;nil&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;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;"Received string: %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;s&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.golang.org/p/vkcuvkYfg3R" rel="noopener noreferrer"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know what &lt;code&gt;nil&lt;/code&gt; channels may be used for, let's add the same feature to our JS channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing &lt;code&gt;nil&lt;/code&gt; channels
&lt;/h2&gt;

&lt;p&gt;As our JS channels don't have a &lt;code&gt;select&lt;/code&gt; for now, our implementation of &lt;code&gt;nil&lt;/code&gt; channels will be partial.&lt;/p&gt;

&lt;p&gt;The equivalent of a &lt;code&gt;nil&lt;/code&gt; channel in JS will be a &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; channel.&lt;/p&gt;

&lt;p&gt;So far when we created or executed send and receive operations, we didn't check at all that the channel key was actually defined or different of &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hence sending to or receiving from a &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt; channel would have ended up in a &lt;code&gt;TypeError&lt;/code&gt; somewhere in our code.&lt;/p&gt;

&lt;p&gt;Now let's modify the existing send operation in order to accept &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt; channel keys and return a never resolved &lt;code&gt;Promise&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&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;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;

    &lt;span class="c1"&gt;// Actually perform send operation...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&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 receive operation uses the &lt;code&gt;doRecv()&lt;/code&gt; function, which is mutualized with the range operation (see previous post).&lt;br&gt;
So let's modify the &lt;code&gt;doRecv()&lt;/code&gt; function to also accept &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt; channel keys and return a never resolved &lt;code&gt;Promise&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doRecv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;chanKey&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;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;

  &lt;span class="c1"&gt;// Actually perform receive operation...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it!&lt;br&gt;
Of course, we just implemented the "bad part" of &lt;code&gt;nil&lt;/code&gt; channels, and we will have to add the good part next time when implementing the &lt;code&gt;select&lt;/code&gt;...&lt;/p&gt;

&lt;h2&gt;
  
  
  What next
&lt;/h2&gt;

&lt;p&gt;Next time we will finally implement the &lt;a href="https://tour.golang.org/concurrency/5" rel="noopener noreferrer"&gt;select&lt;/a&gt;, and complete the full feature set of channels.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this small bonus post, give a ❤️, 💬 leave a comment, or share it with others, and follow me to get notified of my next posts.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>go</category>
      <category>tutorial</category>
      <category>node</category>
    </item>
    <item>
      <title>What the for? One loop to rule them all!</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Tue, 31 Dec 2019 12:37:35 +0000</pubDate>
      <link>https://dev.to/zenika/what-the-for-one-loop-to-rule-them-all-3m82</link>
      <guid>https://dev.to/zenika/what-the-for-one-loop-to-rule-them-all-3m82</guid>
      <description>&lt;p&gt;When I first learned that Go has only one keyword for loops, I thought to myself "What the f***? Aren't they oversimplifying things?".&lt;/p&gt;

&lt;p&gt;Now, looking back, I think getting rid of &lt;code&gt;while&lt;/code&gt; and &lt;code&gt;do...while&lt;/code&gt; in favor of having only &lt;code&gt;for&lt;/code&gt;, is a good choice.&lt;/p&gt;

&lt;p&gt;I wouldn't say this is easier to learn for beginners. Replacing several keywords by several forms of the same keyword doesn't minimize what you have to learn as a total newbie.&lt;/p&gt;

&lt;p&gt;However, having used Go for several years now, I feel comfortable with its &lt;code&gt;for&lt;/code&gt; loop keyword. Writing it or reading it from other people's code always feels simple.&lt;/p&gt;

&lt;p&gt;Now let's have a look at its different syntaxes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forever
&lt;/h2&gt;

&lt;p&gt;Starting with my favorite one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="c"&gt;// Don't try this at home&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;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;"To infinity and beyond!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// This infinite loop prints a message to standard output&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.golang.org/p/3Jm4mtLzoAR"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice and pure, the infinite loop needs only the &lt;code&gt;for&lt;/code&gt; keyword and its brackets.&lt;/p&gt;

&lt;p&gt;This is compact, and in my opinion pretty intuitive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good ol' for
&lt;/h2&gt;

&lt;p&gt;Of course there is the classic &lt;code&gt;for&lt;/code&gt;, with an initialization, a condition, and an afterthought, separated by semicolons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="c"&gt;// Count to ten on standard output:&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;10&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;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;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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.golang.org/p/WVdG-BXOMpp"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the absence of parentheses? Go doesn't have parentheses around statement's parameters.&lt;/p&gt;

&lt;p&gt;Each part may be ommited:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="c"&gt;// This function counts down from n to 1&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;countDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// No initialization is needed&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="o"&gt;&amp;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;n&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;Println&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="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;countDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&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;a href="https://play.golang.org/p/4lIi7rNrIIW"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two semicolons must be kept for the syntax to be valid (only one semicolon is forbidden).&lt;/p&gt;

&lt;p&gt;You may omit all the parts, which is the equivalent of an infinite &lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  For a while
&lt;/h2&gt;

&lt;p&gt;If you need the equivalent of a &lt;code&gt;while&lt;/code&gt;, that is a loop with only a condition, just use &lt;code&gt;for&lt;/code&gt; like you would use a &lt;code&gt;while&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="c"&gt;// This function adds leading zeros to str&lt;/span&gt;
&lt;span class="c"&gt;// in order ot reach a length of n&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;padZeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;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;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;str&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="c"&gt;// Prints "0000000123"&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;padZeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&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;a href="https://play.golang.org/p/uITCWmYNK3F"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not much to say, this is rather intuitive, still no parentheses.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;for...range&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A common use case is to iterate over a list of items.&lt;/p&gt;

&lt;p&gt;This can be done using the &lt;code&gt;range&lt;/code&gt; keyword in conjunction with &lt;code&gt;for&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"May"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"for"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"be"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"with"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"you"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Prints each message preceded by its index&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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;messages&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;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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;&lt;a href="https://play.golang.org/p/8fNEO7k2qZd"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, &lt;code&gt;for...range&lt;/code&gt; allows to retrieve each index and its associated value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;range&lt;/code&gt; may also be used with maps, in which case it retrieves a key instead of an index.&lt;/p&gt;

&lt;p&gt;If you need only the value, the index/key may be discarded using &lt;code&gt;_&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"May"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"for"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"be"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"with"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"you"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Prints each message&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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;messages&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;message&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;&lt;a href="https://play.golang.org/p/Eeo_X1IquNc"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And in case you need only the index/key, the value may be ommited:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"May"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"for"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"be"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"with"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"you"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Prints each message&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="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;messages&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;messages&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.golang.org/p/NAjoynK1EcO"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, if you don't need the index/key or the value, both can be omitted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"May"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"for"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"be"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"with"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"you"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Allows you to iterate len(messages) times&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;messages&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;"Do something..."&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;&lt;a href="https://play.golang.org/p/2uUmnHXFTZq"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;for...range&lt;/code&gt; with channels
&lt;/h2&gt;

&lt;p&gt;Go is well known for its CSP concurrency model, which favors goroutines and channels over threads and mutexes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;for...range&lt;/code&gt; may also be used when receiving values from a channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="c"&gt;// Create a channel&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;send123&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="c"&gt;// Start send123() in a new goroutine&lt;/span&gt;

    &lt;span class="c"&gt;// Receive and print integers from channel&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="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;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="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Send 3 integers through channel&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;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&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;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Close channel&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.golang.org/p/wjlAnWLY8J4"&gt;Run it on Go playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Used on a channel, &lt;code&gt;for...range&lt;/code&gt; will wait for a value to be received at each iteration, blocking the goroutine which is executing it.&lt;/p&gt;

&lt;p&gt;The loop ends when the channel is closed by the sending goroutine.&lt;/p&gt;

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

&lt;p&gt;As you can see having only one keyword for loops doesn't change things much if you were used to C-style languages.&lt;/p&gt;

&lt;p&gt;It makes for rather understandable code, which I think is one of the most important things if you have to work with a team.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this quick introduction to Go's loops, give a ❤️, 💬 leave a comment, or share it with others, and follow me to get notified of my next posts.&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Go channels in JS (4/5): Ranging</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Mon, 23 Dec 2019 23:15:22 +0000</pubDate>
      <link>https://dev.to/zenika/go-channels-in-js-4-5-ranging-ifo</link>
      <guid>https://dev.to/zenika/go-channels-in-js-4-5-ranging-ifo</guid>
      <description>&lt;p&gt;This post is the fourth of a series about how I wrote in JavaScript the equivalent of Go(lang) channels.&lt;/p&gt;

&lt;p&gt;If you haven't already, I highly recommend reading at least the first post before reading this one:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/zenika" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1234%2F61529416-7337-4c59-ab27-aaa666d850fc.png" alt="Zenika"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F170792%2Ff7b3b62a-4900-4579-925a-2bc65de53987.jpeg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/zenika/go-channels-in-js-1-5-sending-and-receiving-2lci" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Go channels in JS (1/5): Sending and Receiving&lt;/h2&gt;
      &lt;h3&gt;Nicolas Lepage for Zenika ・ Dec 2 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#go&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;So far we have built an equivalent of Go channels in JS, which allows us to create channels, buffered or unbuffered, send values to these, receive values from these, and finally close these.&lt;/p&gt;

&lt;p&gt;This time we will use the closing feature we added last time as a base to build a new feature: Ranging.&lt;/p&gt;

&lt;p&gt;First, let's have a look at how to range over a channel in Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ranging over channel
&lt;/h2&gt;

&lt;p&gt;If you remember last time, we used the ability of the receive operator to return two values in order to know if a channel has been closed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// This is like while (true)&lt;/span&gt;
  &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&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;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;i&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 second value returned by the receive operator is a boolean which tells us if something has actually been received.&lt;/p&gt;

&lt;p&gt;However Go offers a better syntax to do the exact same thing, which is &lt;a href="https://tour.golang.org/concurrency/4" rel="noopener noreferrer"&gt;the range operator&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&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;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This range loop will iterate over the values received from &lt;code&gt;ch&lt;/code&gt; until this one is closed.&lt;/p&gt;

&lt;p&gt;Let's take back our &lt;code&gt;send123()&lt;/code&gt; example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;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;// Create an integer channel&lt;/span&gt;

  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;send123&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="c"&gt;// Start send123() in a new goroutine&lt;/span&gt;

  &lt;span class="c"&gt;// Receive an integer from ch and print it until ch is closed&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="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;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="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Send 3 integers to ch&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;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&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;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Close ch&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is much easier to read than last time!&lt;br&gt;
Now how could we transpose this in JS?&lt;/p&gt;

&lt;p&gt;Of course using a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of" rel="noopener noreferrer"&gt;&lt;code&gt;for ... of&lt;/code&gt;&lt;/a&gt; would be nice.&lt;br&gt;
But &lt;code&gt;for ... of&lt;/code&gt; uses the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol" rel="noopener noreferrer"&gt;iterator protocol&lt;/a&gt; which is synchronous, whereas the receive operation is asynchronous.&lt;/p&gt;

&lt;p&gt;Good news, JS has asynchronous iteration since ES2018, which comes with a new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of" rel="noopener noreferrer"&gt;&lt;code&gt;for await ... of&lt;/code&gt;&lt;/a&gt; syntax.&lt;br&gt;
So we could create a new range operation, which would return an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator" rel="noopener noreferrer"&gt;asynchronous iterable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's try this with our &lt;code&gt;send123()&lt;/code&gt; example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;chan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Create a channel&lt;/span&gt;

  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Start send123()&lt;/span&gt;

  &lt;span class="c1"&gt;// Receive a value from ch and log it to console until ch is closed&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Send 3 integers to ch&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;yield&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Close ch&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Nice! Like in Go the code is much easier to understand, even if having a &lt;code&gt;yield&lt;/code&gt; inside a &lt;code&gt;for await ... of&lt;/code&gt; is not simple.&lt;/p&gt;

&lt;p&gt;Now let's implement our new range operation!&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing ranging over channel
&lt;/h2&gt;

&lt;p&gt;As usual we need an operation factory:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RANGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RANGE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RANGE&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;chanKey&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;We have only one &lt;code&gt;chanKey&lt;/code&gt; argument which is the key of the channel we want to iterate over.&lt;/p&gt;

&lt;p&gt;Then we have to handle range operations in the channel middleware:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RANGE&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle range operation&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&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;for await ... of&lt;/code&gt; needs an asynchronous iterable, which is an object able to return an iterator.&lt;br&gt;
A common pattern is to use the same object as iterable and iterator:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RANGE&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asyncIterator&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see &lt;code&gt;it&lt;/code&gt; returns itself when asked for an iterator, and will therefore satisfy the async iterable protocol.&lt;br&gt;
Now &lt;code&gt;it&lt;/code&gt; needs to implement the async iterator protocol.&lt;/p&gt;

&lt;p&gt;All the async iterator protocol needs is an async &lt;code&gt;next()&lt;/code&gt; function, which must return an object with two properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;value&lt;/code&gt; which is the current value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;done&lt;/code&gt;, a boolean which tells us if the iterator has ended, in which case &lt;code&gt;value&lt;/code&gt; may be omitted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This looks a lot like the detailed receive operation we created last time, which returns a scalar with a value and a boolean which tells us if a value was actually received.&lt;br&gt;
The only actual difference is that the boolean is inverted.&lt;/p&gt;

&lt;p&gt;So we should be able to use the &lt;code&gt;doRecv()&lt;/code&gt; function we created last time to implement &lt;code&gt;next()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asyncIterator&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;doRecv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ok&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And this is it! Well that was easy.&lt;br&gt;
Let's try this out on repl.it with our &lt;code&gt;send123()&lt;/code&gt; example (it uses &lt;a href="https://github.com/standard-things/esm" rel="noopener noreferrer"&gt;esm&lt;/a&gt; to benefit from modules):&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@nlepage/Go-channels-in-JS-45-Ranging?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  What next
&lt;/h2&gt;

&lt;p&gt;With ranging done, we are not far from having the full feature set of channels, the only thing missing is &lt;a href="https://tour.golang.org/concurrency/5" rel="noopener noreferrer"&gt;select&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The last post "Go channels in JS (5/5): Selecting" will be a big one, I'll need some time to write it...&lt;br&gt;
In the meantime I might publish some bonus posts (did you know that Go allows receiving from a nil channel?), so stay tuned.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this fourth post, give a ❤️, 💬 leave a comment, or share it with others, and follow me to get notified of my next posts.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>go</category>
      <category>tutorial</category>
      <category>node</category>
    </item>
    <item>
      <title>Go channels in JS (3/5): Closing</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Tue, 17 Dec 2019 07:44:13 +0000</pubDate>
      <link>https://dev.to/zenika/go-channels-in-js-3-5-closing-4l6l</link>
      <guid>https://dev.to/zenika/go-channels-in-js-3-5-closing-4l6l</guid>
      <description>&lt;p&gt;This post is the third of a series about how I wrote in JavaScript the equivalent of Go(lang) channels.&lt;/p&gt;

&lt;p&gt;If you haven't already, I highly recommend reading at least the first post before reading this one:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/nlepage" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2ri0r5U4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--RsbB_i72--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/170792/f7b3b62a-4900-4579-925a-2bc65de53987.jpeg" alt="nlepage image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/zenika/go-channels-in-js-1-5-sending-and-receiving-2lci" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Go channels in JS (1/5): Sending and Receiving&lt;/h2&gt;
      &lt;h3&gt;Nicolas Lepage ・ Dec  2 '19 ・ 11 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#go&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In the previous posts we built an equivalent of Go channels in JS.&lt;br&gt;
We were able to create channels, buffered or unbuffered, send values to these, and receive values from these.&lt;/p&gt;

&lt;p&gt;This time we will add a new feature to our JS channels: Closing.&lt;/p&gt;

&lt;p&gt;But why the heck would we want to close a channel? Let's answer this for a start.&lt;/p&gt;
&lt;h2&gt;
  
  
  Closing channels
&lt;/h2&gt;

&lt;p&gt;Closing a channel in Go is pretty easy, you just have to call the &lt;code&gt;close()&lt;/code&gt; built-in function (built-in functions like &lt;code&gt;close()&lt;/code&gt; and &lt;code&gt;make()&lt;/code&gt; are available without importing any package):&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;example&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;// Create a channel&lt;/span&gt;

  &lt;span class="c"&gt;// Use the channel...&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="c"&gt;// Close the channel&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Closing the channel has several effects.&lt;/p&gt;

&lt;p&gt;First, it is not possible to send values to a closed channel, it will panic (throw an error) if you do.&lt;br&gt;
Therefore it is always the responsibility of the sender to close a channel.&lt;/p&gt;

&lt;p&gt;Second, once the channel's buffer is empty, the information that it is closed will be broadcasted to any further receivers.&lt;/p&gt;

&lt;p&gt;But what does "broadcasting the information that it is closed" mean? How is this done in concrete terms?&lt;br&gt;
Well a receive operation on a closed channel (with no values left in its buffer) will return instantly with a &lt;a href="https://tour.golang.org/basics/12"&gt;zero value&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's take back our &lt;code&gt;send123()&lt;/code&gt; example from the previous posts:&lt;br&gt;
&lt;/p&gt;
&lt;div class="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;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;// Create an integer channel&lt;/span&gt;

  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;send123&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="c"&gt;// Start send123() in a new goroutine&lt;/span&gt;

  &lt;span class="c"&gt;// Receive an integer from ch and print it to stdout 6 times&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="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Prints 1&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="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Prints 2&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="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Prints 3&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="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Prints 0&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="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Prints 0&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="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Prints 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;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Send 3 integers to ch&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="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="c"&gt;// Close &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;As you can see, once &lt;code&gt;ch&lt;/code&gt; is closed, any further receive operation returns the zero value, which is &lt;code&gt;0&lt;/code&gt; for integers.&lt;/p&gt;

&lt;p&gt;We could make a loop to receive integers from &lt;code&gt;ch&lt;/code&gt; and assert that it is closed as soon as we receive &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
But what if we want to send &lt;code&gt;0&lt;/code&gt; over &lt;code&gt;ch&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;We need a better way of knowing if the channel is closed.&lt;br&gt;
And Go provides that by allowing to receive two values from a channel:&lt;br&gt;
&lt;/p&gt;
&lt;div class="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;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="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="n"&gt;ok&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ok&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;"Received:"&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="k"&gt;else&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;"Channel closed"&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 you can see when receiving two values from a channel, the second value is a boolean which tells us whether we actually received something or not, in which case the channel is closed.&lt;/p&gt;

&lt;p&gt;So let's use this second value to build a loop, and iterate over the integers received from &lt;code&gt;send123()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="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;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;// Create an integer channel&lt;/span&gt;

  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;send123&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="c"&gt;// Start send123() in a new goroutine&lt;/span&gt;

  &lt;span class="c"&gt;// Receive an integer from ch and print it until ch is closed&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;// This is like while (true)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&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;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;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="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Send 3 integers to ch&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="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="c"&gt;// Close ch&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now how could we do the same thing in JS?&lt;/p&gt;

&lt;p&gt;In JS it is not possible to return two values, but we can use a scalar.&lt;br&gt;
However the receive operation won't be able know if we want only the value, or a scalar with the value and a boolean...&lt;/p&gt;

&lt;p&gt;We are forced to add an optional argument to the receive operation, which we will use when we want to know if the channel is closed.&lt;br&gt;
Now let's transpose our example to JS:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;chan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Create a channel&lt;/span&gt;

  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Start send123()&lt;/span&gt;

  &lt;span class="c1"&gt;// Receive a value from ch and log it to console until ch is closed&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Send 3 integers to ch&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Close ch&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The second argument of our receive operation allows us to ask for a detailed receive by setting it to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And of course, there is the new close operation that allows us to close the channel.&lt;/p&gt;

&lt;p&gt;Now let's add this closing feature to our JS channels!&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing channel closing
&lt;/h2&gt;

&lt;p&gt;Let's start with the close operation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Close operation
&lt;/h3&gt;

&lt;p&gt;As usual we need an operation factory:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CLOSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLOSE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;close&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CLOSE&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;chanKey&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;This operation needs only  &lt;code&gt;chanKey&lt;/code&gt; which is the key of the channel we want to close.&lt;/p&gt;

&lt;p&gt;Then we also need a boolean in the channel's state in order to know if the channel is closed.&lt;br&gt;
Let's initialize this boolean when we create a channel:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;bufferLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// New closed flag&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Finally we need to handle close operations in the channel middleware:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CLOSE&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`close on closed &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;First we check if the channel was already closed, in which case we throw an error.&lt;br&gt;
If not, we flag the channel as closed.&lt;/p&gt;

&lt;p&gt;However this isn't enough, we also need to drain the waiting receivers out of the receive queue:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CLOSE&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;recver&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nx"&gt;recver&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We are giving a scalar with an &lt;code&gt;undefined&lt;/code&gt; value and a &lt;code&gt;false&lt;/code&gt; boolean to the receiver, meaning that nothing was received and the channel is closed.&lt;br&gt;
It will be the responsibility of the receiver to decide whether to return the scalar or only the value, but we'll talk about that later...&lt;/p&gt;

&lt;p&gt;At this point you may wonder why we aren't checking the channel's buffer or even send queue.&lt;br&gt;
But you have to remember that every operation leaves the channel in a stable state, so if we have receivers in the receive queue we can safely assert that there is no senders in the send queue and no values in the buffer.&lt;/p&gt;

&lt;p&gt;And this is it for the close operation! Let's move on to the receive operation...&lt;/p&gt;
&lt;h3&gt;
  
  
  Receive operation
&lt;/h3&gt;

&lt;p&gt;The receive operation must now be able to return either only the value, or a scalar with the value and a boolean, what we will call a "detailed receive".&lt;/p&gt;

&lt;p&gt;So let's start by adding an optional &lt;code&gt;detail&lt;/code&gt; argument to the operation factory:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RECV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RECV&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;detail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RECV&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;detail&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;&lt;code&gt;detail&lt;/code&gt; defaults to false, so by default a receive operation will return only the value.&lt;/p&gt;

&lt;p&gt;Now let's use this new &lt;code&gt;detail&lt;/code&gt; flag in the channel middleware.&lt;/p&gt;

&lt;p&gt;We could use it in every case where we are returning from a receive operation... But we would duplicate the same code.&lt;br&gt;
Instead, let's extract a new &lt;code&gt;doRecv()&lt;/code&gt; function which will always return a detailed receive:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doRecv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;copyWithin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sender&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="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="kc"&gt;true&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;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;We return a scalar when receiving from the buffer or from the receive queue.&lt;/p&gt;

&lt;p&gt;There is still the third case when we are pushing a receiver in the receive queue, this receiver must be called with a detailed receive, so let's keep this in mind for the send operation.&lt;/p&gt;

&lt;p&gt;We also have to check if the channel is closed.&lt;br&gt;
Receiving values from a closed channel is possible, hence we must do it only if its buffer and send queue are empty, just before pushing to the receive queue:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doRecv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closed&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&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;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;If the channel is closed, we return a scalar with an &lt;code&gt;undefined&lt;/code&gt; value and a &lt;code&gt;false&lt;/code&gt; boolean, meaning that nothing was received.&lt;/p&gt;

&lt;p&gt;Finally let's use our new &lt;code&gt;doRecv()&lt;/code&gt; function in the channel middleware:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RECV&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;doRecv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Pretty simple, we are using the &lt;code&gt;detail&lt;/code&gt; flag only once when &lt;code&gt;doRecv()&lt;/code&gt; returns, to decide whether to return the scalar or only the value.&lt;/p&gt;

&lt;p&gt;And this is it for the receive operation! Let's end with the send operation...&lt;/p&gt;
&lt;h3&gt;
  
  
  Send operation
&lt;/h3&gt;

&lt;p&gt;This one is going to be much simpler.&lt;/p&gt;

&lt;p&gt;The first thing we need to do is check that we are not sending on a closed channel:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`send on closed &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then all we have to do is make sure that we are giving a detailed receive when calling a receiver from the receive queue:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;recver&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We give to the receiver a scalar with the value and a &lt;code&gt;true&lt;/code&gt; boolean, meaning that something has actually been received.&lt;/p&gt;

&lt;p&gt;And we have made it! We are now able to close our JS channels.&lt;br&gt;
Let's try this out on repl.it with our &lt;code&gt;send123()&lt;/code&gt; example (it uses &lt;a href="https://github.com/standard-things/esm"&gt;esm&lt;/a&gt; to benefit from modules):&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@nlepage/Go-channels-in-JS-35-Closing?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  What next
&lt;/h2&gt;

&lt;p&gt;Next time, we are going to take full advantage of what we have built so far, and add a cool feature to our JS channels: &lt;a href="https://tour.golang.org/concurrency/4"&gt;Ranging&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;So I have two more posts coming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go channels in JS (4/5): Ranging&lt;/li&gt;
&lt;li&gt;Go channels in JS (5/5): Selecting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And maybe some bonus posts.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this third one, give a ❤️, 💬 leave a comment, or share it with others, and follow me to get notified of my next posts.&lt;/p&gt;

</description>
      <category>go</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>node</category>
    </item>
    <item>
      <title>Go channels in JS (2/5): Buffering</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Tue, 10 Dec 2019 06:57:04 +0000</pubDate>
      <link>https://dev.to/zenika/go-channels-in-js-2-5-buffering-20ng</link>
      <guid>https://dev.to/zenika/go-channels-in-js-2-5-buffering-20ng</guid>
      <description>&lt;p&gt;This post is the second of a series about how I wrote in JavaScript the equivalent of Go(lang) channels.&lt;/p&gt;

&lt;p&gt;If you haven't already, I highly recommend reading the first post before reading this one:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/zenika" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1234%2F61529416-7337-4c59-ab27-aaa666d850fc.png" alt="Zenika"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F170792%2Ff7b3b62a-4900-4579-925a-2bc65de53987.jpeg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/zenika/go-channels-in-js-1-5-sending-and-receiving-2lci" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Go channels in JS (1/5): Sending and Receiving&lt;/h2&gt;
      &lt;h3&gt;Nicolas Lepage for Zenika ・ Dec 2 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#go&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In the last post we built a basic equivalent of Go channels in JS.&lt;br&gt;
We were able to create channels, send values to these, and receive values from these.&lt;/p&gt;

&lt;p&gt;This time we will add a new feature to our JS channels: Buffering.&lt;/p&gt;

&lt;p&gt;So let's start with a quick presentation of buffered channels in Go.&lt;/p&gt;
&lt;h2&gt;
  
  
  Buffered channels
&lt;/h2&gt;

&lt;p&gt;Last time we saw that the send and receive operations of channels are blocking operations.&lt;br&gt;
A send operation will block until a receive operation is ready on the same channel, and vice versa.&lt;/p&gt;

&lt;p&gt;At least this is true for unbuffered channels, but a channel may have a buffer!&lt;br&gt;
Let's take back our &lt;code&gt;send123()&lt;/code&gt; example from last time, with a buffered channel:&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;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;// Create an integer channel&lt;/span&gt;

  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;send123&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="c"&gt;// Start send123() in a new goroutine&lt;/span&gt;

  &lt;span class="c"&gt;// Receive an integer from ch and print it to stdout 3 times&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="o"&gt;&amp;lt;-&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="o"&gt;&amp;lt;-&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="o"&gt;&amp;lt;-&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="o"&gt;&amp;lt;-&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;func&lt;/span&gt; &lt;span class="n"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Send 3 integers to ch&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="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="c"&gt;// Close &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see &lt;code&gt;make()&lt;/code&gt; accepts a second argument which is the size of the channel's buffer.&lt;br&gt;
Our channel &lt;code&gt;ch&lt;/code&gt; now has a buffer with a size of 3, which means that it is able to store 3 values.&lt;/p&gt;

&lt;p&gt;As a result, &lt;code&gt;send123()&lt;/code&gt; doesn't have to wait for &lt;code&gt;main()&lt;/code&gt; to be ready to receive from &lt;code&gt;ch&lt;/code&gt;.&lt;br&gt;
Of course the order of execution isn't deterministic, however it is possible that &lt;code&gt;send123()&lt;/code&gt; sends the three integers at once to the channel, which will store these into its buffer.&lt;/p&gt;

&lt;p&gt;The send operation becomes a non blocking operation.&lt;br&gt;
And the reverse is also true, as long as &lt;code&gt;ch&lt;/code&gt; has values in its buffer, receiving values from &lt;code&gt;ch&lt;/code&gt; won't be a blocking operation for &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However what happens if the buffer is "too small", if &lt;code&gt;ch&lt;/code&gt; has a buffer of size 1 for example?&lt;br&gt;
Well &lt;code&gt;send123()&lt;/code&gt; will be able to perform only one non blocking send operation, then it will have to wait for a receive operation to free some space in the &lt;code&gt;ch&lt;/code&gt;'s buffer.&lt;/p&gt;

&lt;p&gt;To sum it up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send operations block if the channel's buffer is full&lt;/li&gt;
&lt;li&gt;Receive operations block if the channel's buffer is empty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Buffered channels are often used to smooth the execution of send/receive intensive processings.&lt;br&gt;
With the right buffer size, it allows the different involved goroutines to face very few blocking time.&lt;/p&gt;

&lt;p&gt;Let's transpose our example to JS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;chan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Create a buffered channel&lt;/span&gt;

  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Start send123()&lt;/span&gt;

  &lt;span class="c1"&gt;// Receive a value from ch and log it to console 3 times&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`main() received &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`main() received &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`main() received &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Send 3 integers to ch&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send123() sent 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send123() sent 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send123() sent 3&lt;/span&gt;&lt;span class="dl"&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;The only thing that has changed compared to last time, is the &lt;code&gt;chan()&lt;/code&gt; operation factory which now accepts an optional buffer size.&lt;br&gt;
We also added some logs in order to see the order of execution.&lt;br&gt;
Now let's add this buffering feature to our JS channels!&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing buffered channels
&lt;/h2&gt;

&lt;p&gt;Let's start with buffered channels creation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Buffered channel creation
&lt;/h3&gt;

&lt;p&gt;To begin with, we have to change our &lt;code&gt;chan()&lt;/code&gt; operation factory in order to take a &lt;code&gt;bufferSize&lt;/code&gt; argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bufferSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;bufferSize&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;bufferSize&lt;/code&gt; defaults to &lt;code&gt;0&lt;/code&gt;, so by default we will create an unbuffered channel.&lt;/p&gt;

&lt;p&gt;Last time we decided to create channel keys using the &lt;code&gt;String&lt;/code&gt; constructor, which ensures us a unique reference and gives us a &lt;code&gt;toString()&lt;/code&gt; method out of the box.&lt;br&gt;
We won't change that, but we can add the buffer size in the string for debug purposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextChanId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bufferSize&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;`chan #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextChanId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; { bufferSize: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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 must change our &lt;code&gt;channelMiddleware&lt;/code&gt;, so that it will manage the creation of buffered channels.&lt;/p&gt;

&lt;p&gt;For now our channels' state contained only a receive queue and a send queue.&lt;br&gt;
Let's add the necessary to make buffered channels work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;bufferLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&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 &lt;code&gt;buffer&lt;/code&gt; array will have two purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it will store buffered values&lt;/li&gt;
&lt;li&gt;its length will tell us the buffer's size (or capacity if you prefer)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the &lt;code&gt;bufferLength&lt;/code&gt; integer will tell us how many values there actually are in the buffer.&lt;/p&gt;

&lt;p&gt;This should give us enough information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;does our buffer have values: &lt;code&gt;bufferLength !== 0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;is our buffer at full capacity: &lt;code&gt;bufferLength === buffer.length&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now the fun part! We have to modify the send and receive operations to manage buffered channels.&lt;/p&gt;

&lt;h3&gt;
  
  
  Send to buffered channel
&lt;/h3&gt;

&lt;p&gt;Until now when we sent a value to a channel, we did only two things: check the receive queue for a waiting receiver and send to it, or push a sender in the send queue.&lt;br&gt;
Now we must also check if there is some place left in the buffer before pushing a sender in the send queue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;recver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Store value in the buffer&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;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;Values should be received in the order they were sent so the buffer must be a FIFO queue, this means that we are always going to store values at then end of the buffer.&lt;br&gt;
We cannot push values, because this would change &lt;code&gt;buffer.length&lt;/code&gt; which tells us the buffer's capacity, but we can use &lt;code&gt;bufferLength&lt;/code&gt; to know the index where to store our value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&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="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="k"&gt;return&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;chanState.bufferLength++&lt;/code&gt; allows use to store &lt;code&gt;operation.value&lt;/code&gt; at the current &lt;code&gt;chanState.bufferLength&lt;/code&gt; index and increment it afterward.&lt;/p&gt;

&lt;p&gt;And this it! Now our channels will store values in the buffer as long as there is some space left, and push senders in the send queue only if the buffer is full.&lt;/p&gt;

&lt;h3&gt;
  
  
  Receive from buffered channel
&lt;/h3&gt;

&lt;p&gt;Until now when we received from a channel, all we did was check the send queue for a waiting sender and receive from it, or push a receiver in the receive queue.&lt;br&gt;
Now we must check if the buffer contains any values beforehand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RECV&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Receive from buffer&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sender&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;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;The buffer being be a FIFO queue, we have to take values from the head of the buffer.&lt;br&gt;
And just like when receiving, we cannot use &lt;code&gt;buffer.shift()&lt;/code&gt; or we would accidentally change the buffer's capacity.&lt;/p&gt;

&lt;p&gt;What we should do is read the index &lt;code&gt;0&lt;/code&gt; and then move all the buffer's values one index to the left without changing its length.&lt;br&gt;
Arrays have a method for this called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin" rel="noopener noreferrer"&gt;copyWithin&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copyWithin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also decrement &lt;code&gt;ch.bufferLength&lt;/code&gt; to reflect the new buffer's content.&lt;/p&gt;

&lt;p&gt;But there is still a problem, when we free some space in the buffer, we should check if there are senders in the send queue.&lt;br&gt;
Having a non full buffer and senders in the send queue would be an invalid state for the channel.&lt;/p&gt;

&lt;p&gt;So let's check the send queue when we take a value from the buffer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copyWithin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bufferLength&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is a sender in the send queue, we receive from it and put the value at the end of the buffer.&lt;br&gt;
As a consequence we decrement &lt;code&gt;chanState.bufferLength&lt;/code&gt; only if there is no sender in the send queue.&lt;/p&gt;

&lt;p&gt;And this is it! We now have fully working buffered channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  What next
&lt;/h2&gt;

&lt;p&gt;Next time we are going to see how channels may be &lt;a href="https://tour.golang.org/concurrency/4" rel="noopener noreferrer"&gt;closed&lt;/a&gt;, maybe not the funniest part, but definitely a key feature of channels.&lt;/p&gt;

&lt;p&gt;So I have three more posts coming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go channels in JS (3/5): Closing&lt;/li&gt;
&lt;li&gt;Go channels in JS (4/5): Ranging&lt;/li&gt;
&lt;li&gt;Go channels in JS (5/5): Selecting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you enjoyed this second post, give a ❤️, 💬 leave a comment, or share it with others, and follow me to get notified of my next posts.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>go</category>
      <category>tutorial</category>
      <category>node</category>
    </item>
    <item>
      <title>Go channels in JS (1/5): Sending and Receiving</title>
      <dc:creator>Nicolas Lepage</dc:creator>
      <pubDate>Mon, 02 Dec 2019 12:20:36 +0000</pubDate>
      <link>https://dev.to/zenika/go-channels-in-js-1-5-sending-and-receiving-2lci</link>
      <guid>https://dev.to/zenika/go-channels-in-js-1-5-sending-and-receiving-2lci</guid>
      <description>&lt;p&gt;This post is the first of a series about how I wrote in JavaScript the equivalent of Go(lang) channels.&lt;/p&gt;

&lt;p&gt;I did this mainly for fun, I really like Go's concurrency model, and as a daily JS developer I thought it was a good challenge to recreate it in JS.&lt;/p&gt;

&lt;p&gt;Whether you already know Go's concurrency model or not isn't important, I'll show very simple examples along the way, and it's a good opportunity to learn a different paradigm from &lt;code&gt;Promise&lt;/code&gt; and &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Furthermore, I'm making an extensive use of JS's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*"&gt;generator functions&lt;/a&gt;, and some other funny things such as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap"&gt;&lt;code&gt;WeakMap&lt;/code&gt;&lt;/a&gt; or async iterables (with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of"&gt;&lt;code&gt;for await ... of&lt;/code&gt;&lt;/a&gt;), so you might also learn a few things about JS!&lt;/p&gt;

&lt;p&gt;Now let's start with a short presentation of Go channels and their basic usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go channels
&lt;/h2&gt;

&lt;p&gt;Go has a really simple way of starting new threads (these are very lightweight threads called goroutine) with the &lt;code&gt;go&lt;/code&gt; keyword:&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;func1&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the above example, &lt;code&gt;func1()&lt;/code&gt; will start in a new goroutine and execute concurrently with &lt;code&gt;main()&lt;/code&gt;.&lt;br&gt;
The equivalent in JS would be calling an async function without using &lt;code&gt;await&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;func1&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;func1&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When several functions execute concurrently in JS, it is safe to share some memory between these.&lt;/p&gt;

&lt;p&gt;This is one of the nice properties of JS's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop"&gt;event loop&lt;/a&gt;, as a developer you don't have to ensure that you're accessing memory in a safe way, it is always the case!&lt;/p&gt;

&lt;p&gt;This differs from Go where, if using shared memory, you must protect it using mutex to ensure that only one goroutine at a time is accessing some variable(s).&lt;/p&gt;

&lt;p&gt;However in Go you also have the possibility to avoid the use of shared memory, and that's where channels come in handy:&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;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;// Create an integer channel&lt;/span&gt;

  &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;send123&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="c"&gt;// Start send123() in a new goroutine&lt;/span&gt;

  &lt;span class="c"&gt;// Receive an integer from ch and print it to stdout 3 times&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="o"&gt;&amp;lt;-&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="o"&gt;&amp;lt;-&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="o"&gt;&amp;lt;-&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;func&lt;/span&gt; &lt;span class="n"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Send 3 integers to ch&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="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;In the above example, &lt;code&gt;main()&lt;/code&gt; creates an integer channel, starts &lt;code&gt;send123()&lt;/code&gt; in a new goroutine, and then receives an integer from the channel and prints it to standard output 3 times.&lt;br&gt;
&lt;code&gt;send123()&lt;/code&gt; sends 3 integers to the channel. On each side, the channel operations are blocking (&lt;code&gt;main()&lt;/code&gt; will block until &lt;code&gt;send123()&lt;/code&gt; sends an integer, and vice versa).&lt;/p&gt;

&lt;p&gt;As you can see channels are pretty simple to use, and allow to avoid sharing memory between &lt;code&gt;main()&lt;/code&gt; and &lt;code&gt;send123()&lt;/code&gt; except for the channel reference.&lt;/p&gt;

&lt;p&gt;So basically I've just said earlier that channels are useless in JS 🤪! They resolve the problem of shared memory which doesn't exist in JS...&lt;/p&gt;

&lt;p&gt;But! There's more to channels. They offer a different way of programming concurrent applications, which might feel more natural to a lot of people.&lt;/p&gt;

&lt;p&gt;They also come with some interesting &lt;a href="https://talks.golang.org/2012/concurrency.slide"&gt;concurrency patterns&lt;/a&gt; such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pipeline&lt;/li&gt;
&lt;li&gt;Fan in&lt;/li&gt;
&lt;li&gt;Fan out&lt;/li&gt;
&lt;li&gt;Timeout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, I already said this but I'm going to repeat myself, I did this mainly for fun!&lt;br&gt;
Now let's start exploring how we might implement channels in JS...&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing channels in JS
&lt;/h2&gt;

&lt;p&gt;We now have a rough idea of what Go channels are and how they are used, but how could we implement the same thing in JS?&lt;/p&gt;

&lt;p&gt;We could use &lt;code&gt;async/await&lt;/code&gt; in some different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a plain object to hold the state of a channel, and define &lt;code&gt;send()&lt;/code&gt; and &lt;code&gt;recv()&lt;/code&gt; async functions which would take a channel's state as first argument&lt;/li&gt;
&lt;li&gt;Define a &lt;code&gt;Channel&lt;/code&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes"&gt;prototype&lt;/a&gt; or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes"&gt;ES6 class&lt;/a&gt; which would hold the state of a channel and have &lt;code&gt;send()&lt;/code&gt; and &lt;code&gt;recv()&lt;/code&gt; async methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or we could use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*"&gt;generator functions&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield"&gt;the &lt;code&gt;yield&lt;/code&gt; keyword&lt;/a&gt; to hide the magic away: channels would be just references, and we would &lt;code&gt;yield&lt;/code&gt; receive and send operations on these references.&lt;/p&gt;

&lt;p&gt;I won't really discuss the pros and cons of using one solution or another here, I chose to use generator functions for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generator functions (and the &lt;code&gt;yield&lt;/code&gt; keyword) will allow us to implement channels with a way of working closer  to that of Go channels&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/EmrysMyrddin"&gt;A friend&lt;/a&gt; and I have been developing a generator functions runner framework called &lt;a href="https://github.com/cuillerejs/cuillere"&gt;Cuillere&lt;/a&gt; (🥄 spoon in french) and I love using it 😁&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So now that &lt;del&gt;we&lt;/del&gt; I have decided to use generator functions, we can imagine what the final result would look like.&lt;br&gt;
Let's transpose our Go example with &lt;code&gt;send123()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;chan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Create a channel&lt;/span&gt;

  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Start send123()&lt;/span&gt;

  &lt;span class="c1"&gt;// Receive a value from ch and log it to console 3 times&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;send123&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Send 3 integers to ch&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;Pretty cool! And using the &lt;code&gt;yield&lt;/code&gt; keyword we are going to make sure that &lt;code&gt;recv()&lt;/code&gt; and &lt;code&gt;send()&lt;/code&gt; operations are blocking, just like in Go! (&lt;code&gt;main()&lt;/code&gt; blocks until &lt;code&gt;send123()&lt;/code&gt; sends an integer, and vice versa).&lt;/p&gt;

&lt;p&gt;There are two additional operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;chan()&lt;/code&gt; creates a new channel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fork()&lt;/code&gt; starts the execution of a generator function without waiting for it to complete (this one might look familiar if you are a &lt;a href="https://redux-saga.js.org/"&gt;redux-saga&lt;/a&gt; user)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Great! We have defined what we want, our goal now is to implement all the hidden mechanics which will allow this code to work.&lt;/p&gt;

&lt;p&gt;But before diving into this, let me give you a short presentation of what cuillere is and how it is going to help us.&lt;/p&gt;
&lt;h2&gt;
  
  
  🥄 Cuillere! (queeyeah!)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;CuillereJS is an extensible asynchronous execution framework based on generator functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So you are probably wondering why we created this Cuillere thing in the first place...&lt;br&gt;
Well the goal of Cuillere is to abstract some inevitable technical complexity in plugins, and keep business code as simple and focused as possible.&lt;/p&gt;

&lt;p&gt;At the time, we were working on a NodeJS/GraphQL backend API with a PostgreSQL database, and in order to ensure the integrity of our data we had to manage transactions properly.&lt;/p&gt;

&lt;p&gt;I won't get into the details here, but managing transactions soon became a real pain for two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;using a callback function every time we had to ensure a transaction was opened&lt;/li&gt;
&lt;li&gt;passing the "transaction aware" PostgreSQL client everywhere we had to perform a database operation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our code had become overly complex just because of transactions management... It was hard to read and often buggy!&lt;br&gt;
That is when we created Cuillere, which allowed us to strip our business code from all the complexity of transactions management.&lt;/p&gt;

&lt;p&gt;Here is a simple example of how cuillere is used with PostgreSQL:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cuillere&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cuillere/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;poolMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;transactionMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryMiddleware&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cuillere/postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cllr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cuillere&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;poolMiddleware&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="cm"&gt;/* postgres config */&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="c1"&gt;// Manages connection pool&lt;/span&gt;
  &lt;span class="nx"&gt;transactionMiddleware&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// Manages transactions&lt;/span&gt;
  &lt;span class="nx"&gt;queryMiddleware&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Executes queries&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addUserAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDefault&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cllr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`INSERT INTO addresses (userId, street, postalcode, city)
           VALUES ($1, $2, $3, $4)
           RETURNING *`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postalCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setDefault&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addressId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`UPDATE users
             SET defaultaddressid = $1
             WHERE userid = $2`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;addressId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see the business code doesn't have to manage transactions, neither manipulate PostgreSQL clients.&lt;br&gt;
It is all taken care of by the plugins!&lt;/p&gt;

&lt;p&gt;The plugins are responsible for executing the operations yielded by the business code.&lt;br&gt;
Cuillere gives them a context object, which they can use to store state or communicate for example.&lt;/p&gt;

&lt;p&gt;I will probably write some more about Cuillere itself in the future, for now let's focus back on our JS channels...&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing channels
&lt;/h2&gt;

&lt;p&gt;We are going to need a channel plugin to give to Cuillere, which will take care of channel operations (creation, sending and receiving):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cllr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cuillere&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;cllr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;chan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It is in this &lt;code&gt;channelMiddleware&lt;/code&gt; that we are going to implement all the mechanics to make channels work as expected.&lt;/p&gt;

&lt;p&gt;The signature of a cuillere middleware is pretty simple (the first level of currying isn't necessary, but it is a convention to have a factory):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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 middleware has a first level with the &lt;code&gt;next&lt;/code&gt; and &lt;code&gt;ctx&lt;/code&gt; arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;next&lt;/code&gt; is the next middleware and should be called when the current middleware doesn't know how to handle the received operation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctx&lt;/code&gt; is the context object&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second level of the middleware has the &lt;code&gt;operation&lt;/code&gt; argument, and is called each time an operation is yielded.&lt;/p&gt;

&lt;p&gt;Let's start by implementing all the mechanics for creating a channel.&lt;/p&gt;
&lt;h3&gt;
  
  
  channel creation
&lt;/h3&gt;

&lt;p&gt;The first thing we need is a factory for channel creation operations:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CHAN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CHAN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&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 use an unexported &lt;code&gt;Symbol&lt;/code&gt; to mark the operation and be able to recognize it in the middleware:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create channel&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&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 I said earlier we want the channels to be just references. We could use empty plain objects, but for debugging purposes let's use something a little less opaque:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextChanId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`chan #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextChanId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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 &lt;code&gt;String&lt;/code&gt; constructor gives us a unique reference (&lt;code&gt;new String('foo') !== new String('foo')&lt;/code&gt; is always true), with a ready to use &lt;code&gt;toString()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Creating a new channel reference isn't enough, we also need to initiate the channel's state and store it somewhere.&lt;br&gt;
Cuillere's context is precisely made for storing this kind of information, so let's use it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// another Symbol we created&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// channel's initial state&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We create the channel's key, store it's initial state, then return the key.&lt;br&gt;
We also initialize a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/a&gt; to store the channels' states if not already done (Why a &lt;code&gt;Map&lt;/code&gt;? Well unlike plain objects whose keys need to be plain strings, &lt;code&gt;Map&lt;/code&gt;s accept any type of keys).&lt;/p&gt;

&lt;p&gt;This is not bad but there is still a problem, the &lt;code&gt;Map&lt;/code&gt; will keep the channel's key and state references forever and prevent them to be garbage collected when the channel isn't used anymore...&lt;/p&gt;

&lt;p&gt;Ideally we would like the channel's key and state to be garbage collectable as soon as no one else holds the channel's key reference anymore.&lt;br&gt;
Well this is one of the use cases for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap"&gt;WeakMaps&lt;/a&gt;, their keys are week references therefore their content is naturally cleaned up by the garbage collector.&lt;/p&gt;

&lt;p&gt;Let's use a &lt;code&gt;WeakMap&lt;/code&gt; instead of a &lt;code&gt;Map&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;WeakMap&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 have to decide what the channel's initial state should be. What do we need to make the receive and send operations work?&lt;br&gt;
Something to store waiting senders and receivers should be enough for now, let's call that the receive queue and send queue:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;sendQ&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;Nice! I think we are ready to move on and start implementing the receive and send operations.&lt;/p&gt;

&lt;p&gt;One last thing that can be improved for the channel creation is the &lt;code&gt;WeakMap&lt;/code&gt; initialization.&lt;br&gt;
Cuillere has a special start operation which happens only once just after calling &lt;code&gt;cllr.call()&lt;/code&gt;, let's use this instead of a lazy initialization:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;WeakMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Our complete code now looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isStart&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cuillere/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CHANS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CHANS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CHAN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CHAN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextChanId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`chan #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextChanId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;WeakMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHAN&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;sendQ&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;return&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&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 now the fun begins! Let's start with the receive operation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Receive from a channel
&lt;/h3&gt;

&lt;p&gt;Just like the channel creation, the receive needs an operation factory, except this time we need to give the channel's key from which we want to receive:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RECV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RECV&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RECV&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;chanKey&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;Then we must handle the operation in the middleware:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RECV&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Receive from channel...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&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 fetch the state of the channel from the context using the channel's key of the operation.&lt;/p&gt;

&lt;p&gt;Now there are two possibilities when receiving from a channel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the send queue has senders: we receive from the first sender&lt;/li&gt;
&lt;li&gt;the send queue is empty: we add a receiver in the receive queue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's handle the case of a non empty send queue first:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RECV&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is pretty straightforward, we just &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift"&gt;shift&lt;/a&gt; the first sender from the send queue (&lt;code&gt;shift()&lt;/code&gt; returns &lt;code&gt;undefined&lt;/code&gt; if the send queue is empty).&lt;br&gt;
If the sender is defined we call it to get the value and return it right away.&lt;/p&gt;

&lt;p&gt;Now let's handle the case of the empty send queue:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RECV&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;This is pretty simple too, we create and return a new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;&lt;code&gt;Promise&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push"&gt;push&lt;/a&gt; its resolve function at the end of the receive queue.&lt;br&gt;
As soon as a sender will call the receiver with a value, the &lt;code&gt;Promise&lt;/code&gt; will be resolved.&lt;/p&gt;

&lt;p&gt;As you can see, by using &lt;code&gt;push()&lt;/code&gt; and &lt;code&gt;shift()&lt;/code&gt; on both the receive and send queues, we can make them act as FIFO queues.&lt;/p&gt;

&lt;p&gt;And we are done with the receive operation! Let's move on to the send operation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Send to channel
&lt;/h3&gt;

&lt;p&gt;The send operation's factory looks like the receive operation's one with one more argument:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SEND&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SEND&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;value&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;&lt;code&gt;value&lt;/code&gt; is the value to be sent to the channel.&lt;/p&gt;

&lt;p&gt;Now let's handle the operation in the middleware:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channelMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CHANS&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chanKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Send to channel...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&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;Just like when receiving, there are two possibilities when sending to a channel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the receive queue has receiver: we send to the first receiver&lt;/li&gt;
&lt;li&gt;the receive queue is empty: we add a sender in the send queue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The case of a non empty receive queue should be pretty straightforward:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recvQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;recver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We shift the first receiver from the receive queue and, if it is defined, we call it with the operation's value, then we return right away.&lt;/p&gt;

&lt;p&gt;The empty receive queue case is a little more complex:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SEND&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;We create and return a new &lt;code&gt;Promise&lt;/code&gt;, but this time we cannot push the raw &lt;code&gt;resolve&lt;/code&gt; function in the senders queue.&lt;br&gt;
We have to create a sender arrow function which resolves the &lt;code&gt;Promise&lt;/code&gt; and returns the operation's value.&lt;/p&gt;

&lt;p&gt;🎉 And this is it! We have all we need to make our &lt;code&gt;send123()&lt;/code&gt; example work (we don't need to implement the fork operation which is already built into cuillere).&lt;/p&gt;

&lt;p&gt;The full example is available on repl.it (it uses &lt;a href="https://github.com/standard-things/esm"&gt;esm&lt;/a&gt; in order to benefit of modules):&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@nlepage/Go-channels-in-JS-15-Sending-and-Receiving?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  What next?
&lt;/h2&gt;

&lt;p&gt;As you already know or as you may have guessed, Go channels offer a larger feature set than just sending and receiving values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;channels may have a &lt;a href="https://tour.golang.org/concurrency/3"&gt;buffer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;channels may be &lt;a href="https://tour.golang.org/concurrency/4"&gt;closed&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tour.golang.org/concurrency/4"&gt;&lt;code&gt;range&lt;/code&gt;&lt;/a&gt; lets you iterate over a channel&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tour.golang.org/concurrency/5"&gt;&lt;code&gt;select&lt;/code&gt;&lt;/a&gt; lets you wait on multiple channel operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I have four more posts coming in which I will implement the full feature set of channels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/zenika/go-channels-in-js-2-5-buffering-20ng"&gt;Go channels in JS (2/5): Buffering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Go channels in JS (3/5): Closing&lt;/li&gt;
&lt;li&gt;Go channels in JS (4/5): Ranging&lt;/li&gt;
&lt;li&gt;Go channels in JS (5/5): Selecting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you enjoyed this first post, give a ❤️, 💬 leave a comment, or share it with others, and follow me to get notified of my next posts.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>go</category>
      <category>node</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
