<?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: Edward Odero</title>
    <description>The latest articles on DEV Community by Edward Odero (@edd_odero).</description>
    <link>https://dev.to/edd_odero</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3940308%2Fd1e7ea50-6c99-4327-9a4c-dd298d02d022.jpg</url>
      <title>DEV Community: Edward Odero</title>
      <link>https://dev.to/edd_odero</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/edd_odero"/>
    <language>en</language>
    <item>
      <title>Building DumpTrade a peer-to-peer waste redistribution platform</title>
      <dc:creator>Edward Odero</dc:creator>
      <pubDate>Fri, 28 Aug 2026 11:23:53 +0000</pubDate>
      <link>https://dev.to/edd_odero/building-dumptrade-a-peer-to-peer-waste-redistribution-platform-371n</link>
      <guid>https://dev.to/edd_odero/building-dumptrade-a-peer-to-peer-waste-redistribution-platform-371n</guid>
      <description>&lt;p&gt;The problem&lt;/p&gt;

&lt;p&gt;Households and businesses generate waste that still has value — offcuts, e-waste, packaging, furniture, organic scraps — but most of it ends up dumped or burned simply because there's no easy channel to get it to someone who could reuse it.&lt;/p&gt;

&lt;p&gt;At GreenTechHackathon&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqlhbqm67ymqdsfeaj46v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqlhbqm67ymqdsfeaj46v.png" alt=" " width="799" height="394"&gt;&lt;/a&gt;, my team set out to fix that with DumpTrade: a platform where anyone can post something they don't need, and anyone nearby who could use it can claim it free, fast, and dead simple.&lt;/p&gt;

&lt;p&gt;This post walks through how we designed and built it, the trade-offs we made under a hackathon deadline, and a few implementation details I think are worth sharing.&lt;/p&gt;

&lt;p&gt;The core idea&lt;/p&gt;

&lt;p&gt;The loop is intentionally small:&lt;/p&gt;

&lt;p&gt;Post → Browse → Claim → Collect&lt;/p&gt;

&lt;p&gt;Every other feature exists to support that loop, not distract from it. We deliberately left out things like in-app chat, payments, and admin moderation for the MVP contact info is exchanged directly once something's claimed, and a report/flag button covers moderation for now.&lt;/p&gt;

&lt;p&gt;Tech stack: why plain HTML/CSS/JS&lt;/p&gt;

&lt;p&gt;We built the frontend in vanilla HTML, CSS, and JavaScript — no React, no build step. For a hackathon with a five person team and a tight deadline, that turned out to be the right call:&lt;/p&gt;

&lt;p&gt;Zero tooling to configure or debug when someone's laptop acts up at 2am&lt;br&gt;
Every page (index.html, browse.html, listing.html, post.html, login.html, register.html) is just... a file. Anyone on the team could open and edit any page without stepping on a bundler config.&lt;br&gt;
A small shared api.js module simulates the backend for now — same function names/shapes we'll use once the real backend exists, so swapping in fetch() calls later should be mechanical rather than a rewrite.&lt;br&gt;
dumptrade-frontend/&lt;br&gt;
├── index.html / browse.html / listing.html / post.html / login.html / register.html&lt;br&gt;
├── css/styles.css&lt;br&gt;
└── js/&lt;br&gt;
    ├── api.js        # mock data layer — future home of real API calls&lt;br&gt;
    ├── listings.js    # shared rendering (cards, detail view, toast)&lt;br&gt;
    ├── claim.js       # claim / collect button logic&lt;br&gt;
    ├── auth.js        # login/register form handling&lt;br&gt;
    └── post.js        # photo upload + post form&lt;br&gt;
Claim logic: the one part that actually needed care&lt;/p&gt;

&lt;p&gt;Everything else in the MVP is straightforward CRUD, but the claim flow has a real race condition: what happens if two people click "Claim" on the same listing at nearly the same time?&lt;/p&gt;

&lt;p&gt;We handle it with a simple guard — check the status is still available right before flipping it:&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
function apiClaimListing(id) {&lt;br&gt;
  const l = apiGetListingById(id);&lt;br&gt;
  if (!l) return { ok: false, message: "Listing not found." };&lt;br&gt;
  if (l.status !== "available") {&lt;br&gt;
    return { ok: false, message: "Sorry — this was just claimed by someone else." };&lt;br&gt;
  }&lt;br&gt;
  l.status = "claimed";&lt;br&gt;
  return { ok: true, message: "Claimed!", listing: l };&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;In a real backend this becomes an atomic conditional update (UPDATE ... WHERE status = 'available', checking rows affected), but the logic is the same shape either way — check-then-set needs to be a single indivisible step, or you'll get double-claims.&lt;/p&gt;

&lt;p&gt;Estimating environmental impact without a scale&lt;/p&gt;

&lt;p&gt;One thing judges tend to respond well to: a number. "We helped the environment" is vague; "~340kg diverted from landfill" is a pitch. But we don't have IoT scales at a weekend hackathon.&lt;/p&gt;

&lt;p&gt;Our answer: category-average weight estimates, applied when an item is marked collected.&lt;/p&gt;

&lt;p&gt;Category    Avg weight estimate&lt;br&gt;
Furniture (large)   25kg&lt;br&gt;
E-waste (large) 8kg&lt;br&gt;
Textiles (per bag)  3kg&lt;br&gt;
Construction offcuts    10kg&lt;br&gt;
Organic waste   2kg&lt;/p&gt;

&lt;p&gt;We're upfront about this being an estimate, not a measurement — methodology transparency mattered more to us than a falsely precise number.&lt;/p&gt;

&lt;p&gt;Location filtering&lt;/p&gt;

&lt;p&gt;Since "nearby" matters a lot for something people physically have to go pick up, Browse includes a location filter built from the cities already present in the listings data (parsed from a "City, Area" string) — not full geolocation yet, but enough to make results actually relevant:&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
function cityOf(location) { return location.split(",")[0].trim(); }&lt;/p&gt;

&lt;p&gt;function apiGetListings(filters = {}) {&lt;br&gt;
  return _listings.filter(l =&amp;gt; {&lt;br&gt;
    if (filters.city &amp;amp;&amp;amp; cityOf(l.location) !== filters.city) return false;&lt;br&gt;
    // ...other filters&lt;br&gt;
    return true;&lt;br&gt;
  });&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Real geolocation/maps is on the roadmap once there's a backend to store coordinates.&lt;/p&gt;

&lt;p&gt;What's next&lt;br&gt;
Wire up a real backend (Go or Node — still deciding) and a database&lt;br&gt;
Real auth instead of the current mock login/register screens&lt;br&gt;
Push notifications when something you'd want gets listed nearby&lt;br&gt;
Recurring listings for businesses with regular byproducts (a cafe's daily coffee grounds, a workshop's weekly offcuts)&lt;br&gt;
Try it / see the code&lt;br&gt;
Live demo: [link]&lt;br&gt;
GitHub: [link]&lt;/p&gt;

&lt;p&gt;Built by [Name], [Name], [Name], [Name], and me at [Hackathon Name]. If you're working on something similar or have thoughts on the claim-race-condition approach, I'd love to hear them in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>hackathon</category>
      <category>sustainability</category>
    </item>
    <item>
      <title># Goroutines &amp; Concurrency in Go: A Beginner's Guide</title>
      <dc:creator>Edward Odero</dc:creator>
      <pubDate>Mon, 22 Jun 2026 07:12:41 +0000</pubDate>
      <link>https://dev.to/edd_odero/-goroutines-concurrency-in-go-a-beginners-guide-4k86</link>
      <guid>https://dev.to/edd_odero/-goroutines-concurrency-in-go-a-beginners-guide-4k86</guid>
      <description>&lt;p&gt;&lt;em&gt;By Edward Odero | Apprentice at z01 Kisumu&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;One of the things that makes Go stand out from other programming languages is how it handles &lt;strong&gt;concurrency&lt;/strong&gt;. If you've ever wanted your program to do multiple things at the same time — like fetching data from an API while also writing to a file — Go makes this surprisingly easy with something called &lt;strong&gt;goroutines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk you through what goroutines are, how they work, and how to use them alongside &lt;strong&gt;channels&lt;/strong&gt; to build concurrent programs in Go.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Concurrency?
&lt;/h2&gt;

&lt;p&gt;Concurrency means doing multiple things at the same time (or at least, making progress on multiple tasks at once). Think of it like a chef cooking multiple dishes simultaneously — they don't finish one dish before starting another; they manage them all in parallel.&lt;/p&gt;

&lt;p&gt;In Go, &lt;strong&gt;goroutines&lt;/strong&gt; are the building blocks of concurrency.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a Goroutine?
&lt;/h2&gt;

&lt;p&gt;A goroutine is a &lt;strong&gt;lightweight thread&lt;/strong&gt; managed by the Go runtime. Unlike threads in other languages, goroutines are incredibly cheap — you can run thousands (even millions) of them without breaking a sweat.&lt;/p&gt;

&lt;p&gt;You start a goroutine simply by using the &lt;code&gt;go&lt;/code&gt; keyword before a function call:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from a goroutine!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// This runs concurrently&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Wait for the goroutine to finish&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main function done"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello from a goroutine!
Main function done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Notice the &lt;code&gt;time.Sleep&lt;/code&gt;? Without it, the &lt;code&gt;main&lt;/code&gt; function might finish and exit before the goroutine gets a chance to run. We'll see a better way to handle this shortly.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem: Goroutines Don't Wait
&lt;/h2&gt;

&lt;p&gt;When the &lt;code&gt;main&lt;/code&gt; function exits, all goroutines are killed — even if they haven't finished. This is why we need a way to &lt;strong&gt;synchronize&lt;/strong&gt; goroutines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 1: &lt;code&gt;sync.WaitGroup&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;WaitGroup&lt;/code&gt; lets you wait for a collection of goroutines to finish:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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;wg&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Signal that this goroutine is done&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;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

    &lt;span class="n"&gt;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;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"goroutines!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&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;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Tell WaitGroup to expect one more goroutine&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;printMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Block until all goroutines are done&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All goroutines finished!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output (order may vary):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from
Hello
goroutines!
All goroutines finished!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Notice the order may vary! That's concurrency in action — goroutines don't always finish in the order they were started.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Channels: Goroutines Talking to Each Other
&lt;/h2&gt;

&lt;p&gt;Goroutines are great, but what if you want them to &lt;strong&gt;share data safely&lt;/strong&gt;? That's where &lt;strong&gt;channels&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;A channel is like a pipe — one goroutine puts data in, another takes it out.&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&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;total&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&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;n&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;nums&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="c"&gt;// Send result to channel&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9&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="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;// Split the work between two goroutines&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ch&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;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;5&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="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;part1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part2&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="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="c"&gt;// Receive both results&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;"Total:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;part2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total: 55
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, two goroutines each sum half the slice, then send their results back through the channel. Clean, safe, and concurrent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Buffered vs Unbuffered Channels
&lt;/h2&gt;

&lt;p&gt;By default, channels are &lt;strong&gt;unbuffered&lt;/strong&gt; — a sender blocks until a receiver is ready (and vice versa).&lt;/p&gt;

&lt;p&gt;You can create a &lt;strong&gt;buffered channel&lt;/strong&gt; that holds a limited number of values without a receiver being ready:&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;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Buffered channel with capacity 3&lt;/span&gt;

&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="c"&gt;// Doesn't block&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="c"&gt;// Doesn't block&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="c"&gt;// Doesn't block&lt;/span&gt;
&lt;span class="c"&gt;// ch &amp;lt;- 4 // This would block! Buffer is full&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;// 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;// 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;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The &lt;code&gt;select&lt;/code&gt; Statement
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;select&lt;/code&gt; statement lets a goroutine wait on multiple channels at once — like a switch statement, but for channels:&lt;br&gt;
&lt;/p&gt;

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

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

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

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ch1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="s"&gt;"one"&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ch2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="s"&gt;"two"&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg1&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;ch1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg1&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;msg2&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;ch2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg2&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;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Received: one
Received: two
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;select&lt;/code&gt; picks whichever channel is ready first — perfect for handling timeouts or multiple data sources.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;What it Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go func()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Starts a goroutine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sync.WaitGroup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Waits for goroutines to finish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a channel for safe communication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Buffered channels&lt;/td&gt;
&lt;td&gt;Allow sending without an immediate receiver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;select&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Listens on multiple channels at once&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;Goroutines and channels are at the heart of what makes Go so powerful for building concurrent and scalable programs. The syntax is clean, the mental model is simple, and the performance is excellent.&lt;/p&gt;

&lt;p&gt;As a beginner learning Go at z01 Kisumu, this was one of those topics that really made me appreciate the language. The fact that you can spin up thousands of goroutines with just the &lt;code&gt;go&lt;/code&gt; keyword is honestly mind-blowing compared to threading in other languages.&lt;/p&gt;

&lt;p&gt;If you're just starting with Go, I encourage you to experiment with goroutines — try building a small program that fetches data concurrently or processes a list in parallel. You'll be amazed at how approachable it is!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Feel free to drop a comment if you have questions or want to share your own experience with Go concurrency.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>concurrency</category>
    </item>
  </channel>
</rss>
