<?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: Steve Omollo</title>
    <description>The latest articles on DEV Community by Steve Omollo (@steve_omollo).</description>
    <link>https://dev.to/steve_omollo</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%2F3927196%2F470d5a9e-a050-4b15-8449-a00ba1c95b3b.jpg</url>
      <title>DEV Community: Steve Omollo</title>
      <link>https://dev.to/steve_omollo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/steve_omollo"/>
    <language>en</language>
    <item>
      <title>I Chose Buffalo for a 48-Hour Hackathon. Then I Had to Figure Out How to Use It</title>
      <dc:creator>Steve Omollo</dc:creator>
      <pubDate>Wed, 02 Sep 2026 09:14:45 +0000</pubDate>
      <link>https://dev.to/steve_omollo/i-chose-buffalo-for-a-48-hour-hackathon-then-i-had-to-figure-out-how-to-use-it-5bce</link>
      <guid>https://dev.to/steve_omollo/i-chose-buffalo-for-a-48-hour-hackathon-then-i-had-to-figure-out-how-to-use-it-5bce</guid>
      <description>&lt;p&gt;I had worked with Go before.&lt;/p&gt;

&lt;p&gt;I had also worked with Bitcoin.&lt;/p&gt;

&lt;p&gt;What I had &lt;strong&gt;not&lt;/strong&gt; worked with was a Go web framework.&lt;/p&gt;

&lt;p&gt;Then came a 48-hour GreenTech hackathon at Zone01 Kisumu.&lt;/p&gt;

&lt;p&gt;Naturally, I decided to change that.&lt;/p&gt;

&lt;p&gt;Not because I had carefully compared every Go framework and found the perfect one. Not because I had years of experience building production applications with Go. I simply researched some of the popular Go backend frameworks for beginners, came across Buffalo, and thought:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Well, Buffalo it is."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That decision would come back to haunt me a little.&lt;/p&gt;

&lt;p&gt;But first, we had a problem to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  From BSF farming to organic waste
&lt;/h2&gt;

&lt;p&gt;The hackathon was organized around broad problem tracks. Teams would choose a track and then narrow it down to a specific problem.&lt;/p&gt;

&lt;p&gt;Our group settled on the &lt;strong&gt;waste management&lt;/strong&gt; track.&lt;/p&gt;

&lt;p&gt;The initial idea came from BSF — Black Soldier Fly farming. BSF farming uses organic waste as part of the process, and somewhere in our discussions, the idea clicked:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if organic waste could be treated as a resource rather than simply waste?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But then we asked ourselves whether we should build the entire idea specifically around BSF farming.&lt;/p&gt;

&lt;p&gt;We eventually decided against narrowing it that much.&lt;/p&gt;

&lt;p&gt;Instead, we would build something broader around &lt;strong&gt;organic waste recycling&lt;/strong&gt;, while still using the BSF farming cycle in our pitch because it was a relevant and familiar use case.&lt;/p&gt;

&lt;p&gt;That became the foundation for &lt;strong&gt;RegenFeed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The idea was fairly simple.&lt;/p&gt;

&lt;p&gt;There are businesses and other large producers generating organic waste. There are farmers and other people who can make use of that waste.&lt;/p&gt;

&lt;p&gt;Why not create a platform that connects the two?&lt;/p&gt;

&lt;h2&gt;
  
  
  Dividing the work
&lt;/h2&gt;

&lt;p&gt;Once we had the direction, we divided the work and started researching our individual responsibilities.&lt;/p&gt;

&lt;p&gt;I was part of the backend team, which had three people.&lt;/p&gt;

&lt;p&gt;My responsibility was the backend core — broadly covering the database, authentication, and core migrations.&lt;/p&gt;

&lt;p&gt;That was also when I started researching which framework I should use.&lt;/p&gt;

&lt;p&gt;I already knew Go, but I had never used a framework for building a Go web application.&lt;/p&gt;

&lt;p&gt;So I searched.&lt;/p&gt;

&lt;p&gt;And Buffalo appeared.&lt;/p&gt;

&lt;p&gt;I knew there were other options. I just hadn't used any of them before. At that point, Buffalo looked like a reasonable starting point for someone new to the concept of Go frameworks.&lt;/p&gt;

&lt;p&gt;So I committed to it.&lt;/p&gt;

&lt;p&gt;Looking back, it was definitely a premature judgment.&lt;/p&gt;

&lt;p&gt;But it made sense at the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  "You've chosen Buffalo? Then you guide us."
&lt;/h2&gt;

&lt;p&gt;There was one small problem.&lt;/p&gt;

&lt;p&gt;I was learning Buffalo.&lt;/p&gt;

&lt;p&gt;My teammates didn't necessarily know that.&lt;/p&gt;

&lt;p&gt;I remember pushing my first commit. Somewhere in the project they saw &lt;code&gt;buffalo&lt;/code&gt;, and that was enough for them to realize what framework I had chosen.&lt;/p&gt;

&lt;p&gt;Then came something along the lines of:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"You've settled on Buffalo? Buffalo it is. You guide us through it."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That sent shivers down my spine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guide you?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I had just started learning it myself.&lt;/p&gt;

&lt;p&gt;But that was the situation.&lt;/p&gt;

&lt;p&gt;So I started figuring it out.&lt;/p&gt;

&lt;p&gt;And honestly, my first impression of Buffalo was magical.&lt;/p&gt;

&lt;p&gt;You run a command — sometimes one that doesn't seem directly related to what you're trying to accomplish — and suddenly something has happened.&lt;/p&gt;

&lt;p&gt;A model appears.&lt;/p&gt;

&lt;p&gt;A migration is generated.&lt;/p&gt;

&lt;p&gt;Some project structure is created.&lt;/p&gt;

&lt;p&gt;Something is wired up.&lt;/p&gt;

&lt;p&gt;And you're sitting there thinking:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Wait. What just happened?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's one of the strange things about frameworks.&lt;/p&gt;

&lt;p&gt;They can make development incredibly fast, but they can also hide a lot of what is actually happening underneath.&lt;/p&gt;

&lt;p&gt;At times I felt like some of the commands were so shortened or abstracted that I could get something working without necessarily knowing the underlying SQL, module creation, or all the individual steps that would have been required without the framework.&lt;/p&gt;

&lt;p&gt;That was both exciting and slightly terrifying.&lt;/p&gt;

&lt;h2&gt;
  
  
  The framework makes things easier — until it doesn't
&lt;/h2&gt;

&lt;p&gt;This hackathon taught me something I hadn't really understood about frameworks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frameworks do make work easier.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But only if you know what to do with them.&lt;/p&gt;

&lt;p&gt;If you don't understand the framework, you can end up in a much worse situation than if you had simply used the standard library.&lt;/p&gt;

&lt;p&gt;And I experienced that firsthand.&lt;/p&gt;

&lt;p&gt;As the backend started taking shape, the frontend team was already moving.&lt;/p&gt;

&lt;p&gt;They kept reminding us that the backend was supposed to come first so that they could build against the endpoints.&lt;/p&gt;

&lt;p&gt;They waited.&lt;/p&gt;

&lt;p&gt;And waited.&lt;/p&gt;

&lt;p&gt;Eventually, they decided to start anyway.&lt;/p&gt;

&lt;p&gt;The agreement became: &lt;em&gt;we'll sort out the endpoint issues later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That "later" eventually arrived.&lt;/p&gt;

&lt;p&gt;And it arrived with very little sleep.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Buffalo met Svelte
&lt;/h2&gt;

&lt;p&gt;The integration between the backend and the Svelte frontend was probably one of the hardest parts of the hackathon for me.&lt;/p&gt;

&lt;p&gt;I pushed my work to the remote repository, expecting that we'd bring everything together and continue.&lt;/p&gt;

&lt;p&gt;Instead, we got conflicts.&lt;/p&gt;

&lt;p&gt;Things weren't communicating properly.&lt;/p&gt;

&lt;p&gt;Work that had made sense in isolation suddenly had to work with everyone else's work.&lt;/p&gt;

&lt;p&gt;And by then, I was exhausted.&lt;/p&gt;

&lt;p&gt;It was almost morning.&lt;/p&gt;

&lt;p&gt;At that point, I honestly can't give you a perfectly technical explanation of everything that went wrong. My brain was already running on fumes.&lt;/p&gt;

&lt;p&gt;What I remember is debugging.&lt;/p&gt;

&lt;p&gt;And needing help.&lt;/p&gt;

&lt;p&gt;And eventually putting lunch on the line.&lt;/p&gt;

&lt;p&gt;One of my teammates and I had developed a little system during the hackathon: whenever I got stuck and needed her help, we'd put sweets — and sometimes lunch — at stake.&lt;/p&gt;

&lt;p&gt;I'd owe her one.&lt;/p&gt;

&lt;p&gt;This was one of those moments.&lt;/p&gt;

&lt;p&gt;And somehow, we got through it.&lt;/p&gt;

&lt;p&gt;That's another thing I learned during the hackathon:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Group work is magical.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I would advocate for it any day.&lt;/p&gt;

&lt;p&gt;Someone gets tired. Someone gets stuck. Someone's brain simply stops cooperating.&lt;/p&gt;

&lt;p&gt;And somehow, the work continues because somebody else is still going.&lt;/p&gt;

&lt;h2&gt;
  
  
  What RegenFeed actually did
&lt;/h2&gt;

&lt;p&gt;The MVP revolved around two main types of users:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Waste producers&lt;/strong&gt; and &lt;strong&gt;farmers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A waste producer could list organic waste on the platform.&lt;/p&gt;

&lt;p&gt;The listing could contain information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the type of waste or its composition, such as carbohydrates, protein, or vitamins&lt;/li&gt;
&lt;li&gt;the weight available&lt;/li&gt;
&lt;li&gt;the price&lt;/li&gt;
&lt;li&gt;a picture&lt;/li&gt;
&lt;li&gt;the producer's locality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A farmer could then log into the platform, browse or search through available waste, find something useful, and place an order.&lt;/p&gt;

&lt;p&gt;We also incorporated Bitcoin Lightning into the concept.&lt;/p&gt;

&lt;p&gt;The producer could price the waste in satoshis, and when a farmer initiated an order, the platform could initiate a Lightning invoice for payment.&lt;/p&gt;

&lt;p&gt;The physical exchange between the farmer and producer, however, happened outside the platform.&lt;/p&gt;

&lt;p&gt;That distinction mattered.&lt;/p&gt;

&lt;p&gt;We weren't trying to become a logistics company in 48 hours.&lt;/p&gt;

&lt;p&gt;We were trying to create the digital marketplace connecting the two sides.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part we didn't solve
&lt;/h2&gt;

&lt;p&gt;And this is where being honest about hackathons matters.&lt;/p&gt;

&lt;p&gt;We had an MVP.&lt;/p&gt;

&lt;p&gt;But it wasn't a finished product.&lt;/p&gt;

&lt;p&gt;The payment implementation was about as basic as we could make it within the time available. Questions around security, platform sustainability, and exactly how the business would make money weren't fully demonstrated.&lt;/p&gt;

&lt;p&gt;There were also features that weren't completely implemented on the backend.&lt;/p&gt;

&lt;p&gt;Every time we solved one issue, another unfinished piece seemed to appear.&lt;/p&gt;

&lt;p&gt;So when I say we built RegenFeed, I don't mean we built a production-ready marketplace.&lt;/p&gt;

&lt;p&gt;We built a &lt;strong&gt;proof of concept under a 48-hour constraint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There was still a lot pending.&lt;/p&gt;

&lt;p&gt;And that's okay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three minutes
&lt;/h2&gt;

&lt;p&gt;Eventually, we had to present.&lt;/p&gt;

&lt;p&gt;We had an MVP, and we had a story to tell.&lt;/p&gt;

&lt;p&gt;Then we discovered another challenge:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three minutes is not a lot of time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our idea had to be compressed into those three minutes, while still explaining the problem, the solution, the marketplace, the organic waste cycle, and the role of Bitcoin Lightning.&lt;/p&gt;

&lt;p&gt;The competition was stiff.&lt;/p&gt;

&lt;p&gt;The first three teams received prizes and recognition.&lt;/p&gt;

&lt;p&gt;We weren't among them.&lt;/p&gt;

&lt;p&gt;But the judges did give us something valuable: they acknowledged that the underlying idea was sound.&lt;/p&gt;

&lt;p&gt;For me, that was enough to make the experience worthwhile.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do differently
&lt;/h2&gt;

&lt;p&gt;If I were starting that hackathon again, I'd change one major thing.&lt;/p&gt;

&lt;p&gt;I would get comfortable with the backend framework and the core endpoint setup &lt;strong&gt;as quickly as possible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The frontend team needed endpoints to move, and I took too long getting there.&lt;/p&gt;

&lt;p&gt;A lot of the integration pressure later came from that delay.&lt;/p&gt;

&lt;p&gt;I'd also establish the API contract much earlier.&lt;/p&gt;

&lt;p&gt;Instead of waiting until everyone had built their pieces and then trying to make them communicate, I'd want the frontend and backend teams to agree early on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what endpoints exist&lt;/li&gt;
&lt;li&gt;what requests look like&lt;/li&gt;
&lt;li&gt;what responses look like&lt;/li&gt;
&lt;li&gt;what authentication looks like&lt;/li&gt;
&lt;li&gt;what data structures we're sharing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That would have saved us a lot of pain later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Buffalo taught me
&lt;/h2&gt;

&lt;p&gt;I still haven't mastered Buffalo.&lt;/p&gt;

&lt;p&gt;And I don't think I need to pretend that I did.&lt;/p&gt;

&lt;p&gt;What the hackathon gave me was something more useful: &lt;strong&gt;I became less afraid of unfamiliar frameworks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before this experience, I might have looked at a new framework and thought:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I don't know this. I'll stick with what I know."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now my reaction is closer to:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I don't know this yet. Let's figure it out."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's progress.&lt;/p&gt;

&lt;p&gt;I'm still more comfortable with Go's standard library at the moment. And I suspect that will continue to change as I explore more frameworks and build more applications.&lt;/p&gt;

&lt;p&gt;But now I know something I didn't know before:&lt;/p&gt;

&lt;p&gt;A framework isn't magic.&lt;/p&gt;

&lt;p&gt;It is a collection of decisions and abstractions designed to make certain things easier.&lt;/p&gt;

&lt;p&gt;The trick is understanding enough of those abstractions that they work &lt;strong&gt;for&lt;/strong&gt; you rather than becoming another problem you have to fight.&lt;/p&gt;

&lt;p&gt;And sometimes, the fastest way to learn that is to choose a framework on a questionable assumption, tell your teammates you'll guide them through it, and then spend the next 48 hours figuring out how to actually do it.&lt;/p&gt;

&lt;p&gt;That's pretty much what happened to me.&lt;/p&gt;

&lt;p&gt;I chose Buffalo.&lt;/p&gt;

&lt;p&gt;Then Buffalo chose me.&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>go</category>
      <category>webdev</category>
      <category>buffalo</category>
    </item>
    <item>
      <title>Structuring Go Projects For Growth with Packages</title>
      <dc:creator>Steve Omollo</dc:creator>
      <pubDate>Thu, 30 Jul 2026 20:11:33 +0000</pubDate>
      <link>https://dev.to/steve_omollo/structuring-go-projects-for-growth-with-packages-221j</link>
      <guid>https://dev.to/steve_omollo/structuring-go-projects-for-growth-with-packages-221j</guid>
      <description>&lt;p&gt;Previously, we built a complete CRUD API for managing tasks.&lt;/p&gt;

&lt;p&gt;Although everything works, our entire application currently lives inside a single &lt;code&gt;main.go&lt;/code&gt; file. This approach is fine for small examples, but as projects grow, a single file quickly becomes difficult to navigate and maintain.&lt;/p&gt;

&lt;p&gt;In this article, we'll reorganize our API into multiple packages, giving each part of the application a clear responsibility while still using Go's standard library.&lt;/p&gt;

&lt;p&gt;By the end, you'll understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why Go projects are split into packages&lt;/li&gt;
&lt;li&gt;how to organize code into folders&lt;/li&gt;
&lt;li&gt;how to create your own packages&lt;/li&gt;
&lt;li&gt;how to import your own code&lt;/li&gt;
&lt;li&gt;how separation of concerns makes applications easier to maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 — Our Current Project
&lt;/h2&gt;

&lt;p&gt;Our project currently looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-crud-api/
├─ go.mod
└─ main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage, every part of our application lives inside a single file. Our data model, HTTP handler, routing, and server startup code are still mixed together.&lt;/p&gt;

&lt;p&gt;For a project with only a few features, this isn't a problem. In fact, keeping in one file can make learning easier because all the code is in one place.&lt;/p&gt;

&lt;p&gt;However, applications rarely stay this small.&lt;/p&gt;

&lt;p&gt;Imagine adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user authentication&lt;/li&gt;
&lt;li&gt;logging&lt;/li&gt;
&lt;li&gt;middleware&lt;/li&gt;
&lt;li&gt;request validation&lt;/li&gt;
&lt;li&gt;database connections&lt;/li&gt;
&lt;li&gt;configuration files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Very quickly, &lt;code&gt;main.go&lt;/code&gt; would become hundreds of lines long, making the application harder to read and maintain.&lt;/p&gt;

&lt;p&gt;Instead of putting everything into one file, Go encourages us to group related code together using packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Create the Project Structure
&lt;/h2&gt;

&lt;p&gt;We'll reorganize the project into separate folders.&lt;/p&gt;

&lt;p&gt;Our project will now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-crud-api/
├─ go.mod
├─ main.go
├─ handlers/
│  └─ tasks.go
└─ models/
   └─ task.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than one file doing everything, each folder now has a specific purpose.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;main.go&lt;/code&gt; starts the server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;handlers&lt;/code&gt; contains functions that process incoming HTTP requests.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;models&lt;/code&gt; defines the application's data structures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This idea is known as &lt;strong&gt;separation of concerns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of one file handling every responsibility, each package focuses on one job.&lt;/p&gt;

&lt;p&gt;As your application grows, this organization makes it much easier to locate code, fix bugs, and add new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Move the Task Struct
&lt;/h2&gt;

&lt;p&gt;Create a folder named &lt;code&gt;models&lt;/code&gt;, then create a file called &lt;code&gt;task.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following code:&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;models&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"title"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down.&lt;/p&gt;

&lt;p&gt;The first line is:&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;models&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every Go source file belongs to a package.&lt;/p&gt;

&lt;p&gt;A package is simply a way of grouping related code together.&lt;/p&gt;

&lt;p&gt;Think of a package as a folder that contains code with a common purpose.&lt;/p&gt;

&lt;p&gt;In our project, the &lt;code&gt;models&lt;/code&gt; package will contain the structures that represent our application's data.&lt;/p&gt;

&lt;p&gt;In this case, that data is our &lt;code&gt;Task&lt;/code&gt; struct.&lt;/p&gt;

&lt;p&gt;Moving the struct into its own package makes it reusable throughout the application without duplicating code.&lt;/p&gt;

&lt;p&gt;Later, if we add &lt;code&gt;User&lt;/code&gt; or &lt;code&gt;Project&lt;/code&gt; struct, they can also live inside the &lt;code&gt;models&lt;/code&gt; package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Create the Handler
&lt;/h2&gt;

&lt;p&gt;Now we'll move the CRUD logic from &lt;code&gt;main.go&lt;/code&gt; into the &lt;code&gt;handlers&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Most of the code is identical to what we wrote in the previous article. The main difference is that now it lives in its own package and uses the &lt;code&gt;Task&lt;/code&gt; struct from the &lt;code&gt;models&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Create a folder named &lt;code&gt;handlers&lt;/code&gt;, then add a file called &lt;code&gt;tasks.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following code:&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;handlers&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"go-crud-api/models"&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;tasks&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TaskHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodGet&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPost&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;

        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPut&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;

        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;updatedTask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;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;task&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;tasks&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;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tasks&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;
                &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;return&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Task not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodDelete&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;taskToDelete&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;

        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;taskToDelete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;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;task&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;tasks&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;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;taskToDelete&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tasks&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="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task deleted"&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="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Task not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Method not allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusMethodNotAllowed&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 file now contains the same CRUD logic from the previous article, but it has been moved into its own package and updated to use the &lt;code&gt;models.Task&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;You might be wondering why the &lt;code&gt;tasks&lt;/code&gt; slice wasn't moved into the &lt;code&gt;models&lt;/code&gt; package along with the &lt;code&gt;Task&lt;/code&gt; struct.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;models&lt;/code&gt; package is responsible for defining the shape of our data, while the &lt;code&gt;handlers&lt;/code&gt; package is responsible for processing HTTP requests. Since we're still storing tasks in memory for simplicity, keeping the slice in the handler avoids introducing another package before it's needed.&lt;/p&gt;

&lt;p&gt;In a larger application, this data would typically be managed by a database or a dedicated storage layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's different?
&lt;/h2&gt;

&lt;p&gt;You may notice a few differences compared to the previous article.&lt;/p&gt;

&lt;p&gt;First, the package declaration is now:&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;handlers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of:&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because this file belongs to the &lt;code&gt;handlers&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Second, we import our own package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="s"&gt;"go-crud-api/models"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to use the &lt;code&gt;Task&lt;/code&gt; struct that now lives inside the &lt;code&gt;models&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Finally, the handler is named &lt;code&gt;TaskHandler&lt;/code&gt; instead of &lt;code&gt;taskHandler&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because it begins with a capital letter, it is exported and can be accessed from &lt;code&gt;main.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we left the function names as &lt;code&gt;taskHandler&lt;/code&gt;, Go would report an error because functions that begin with a lowercase letter are only visible within the same package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Import Paths
&lt;/h2&gt;

&lt;p&gt;You might be wondering where this import path comes from:&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="s"&gt;"go-crud-api/models"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part, &lt;code&gt;go-crud-api&lt;/code&gt;, is the module name we created earlier when we ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init go-crud-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go uses the module name as the base for importing packages within the same project.&lt;/p&gt;

&lt;p&gt;If your module had a different name, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init task-manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the import would become:&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="s"&gt;"task-manager/models"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the &lt;code&gt;handlers&lt;/code&gt; package to access exported identifiers from the &lt;code&gt;models&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;This is why it's important that the import path matches the module name in your &lt;code&gt;go.mod&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Update main.go
&lt;/h2&gt;

&lt;p&gt;Now that the application has been split into packages, &lt;code&gt;main.go&lt;/code&gt; becomes much smaller.&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;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"go-crud-api/handlers"&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaskHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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;Since &lt;code&gt;TaskHandler now lives in another package, we must import the&lt;/code&gt;handlers&lt;code&gt;package before we can use it. Once imported, we access the exported functions using the package name followed by a dot, such as&lt;/code&gt;handlers.TaskHandler`.&lt;/p&gt;

&lt;p&gt;Notice how little code remains.&lt;/p&gt;

&lt;p&gt;Instead of containing all the CRUD logic, &lt;code&gt;main.go&lt;/code&gt; now has a single responsibility: starting the application.&lt;/p&gt;

&lt;p&gt;This makes the file much easier to read.&lt;/p&gt;

&lt;p&gt;Whenever we need to modify how tasks are handled, we know exactly where to look: the &lt;code&gt;handlers&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Keeping each package focused on one responsibility makes applications easier to understand as they grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Exported Names
&lt;/h2&gt;

&lt;p&gt;You may have noticed that our handler function is now called:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;go&lt;br&gt;
TaskHandler&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;instead of:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;go&lt;br&gt;
taskHandler&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This change is important.&lt;/p&gt;

&lt;p&gt;In Go, any name that begins with a capital letter is &lt;strong&gt;exported&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Exported identifiers can be accessed from other packages.&lt;/p&gt;

&lt;p&gt;Names beginning with a lowercase letter remain private to the package where they are declared.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;go&lt;br&gt;
func TaskHandler(...) {}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;can be used from &lt;code&gt;main.go&lt;/code&gt;, while:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;go&lt;br&gt;
func taskHandler(...) {}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;cannot.&lt;/p&gt;

&lt;p&gt;This convention is one of the simplest yet most distinctive features of Go, and you'll use it throughout the standard library.&lt;/p&gt;

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

&lt;p&gt;Although our API behaves exactly as before, its internal structure is much cleaner.&lt;/p&gt;

&lt;p&gt;Here's what changed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Everything lived in &lt;code&gt;main.go&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Code is split into packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One file handled everything&lt;/td&gt;
&lt;td&gt;Each package has one responsibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Difficult to grow&lt;/td&gt;
&lt;td&gt;Easier to maintain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Harder to navigate&lt;/td&gt;
&lt;td&gt;Easier to understand&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We haven't added any new features yet—but we've made our project much easier to extend.&lt;/p&gt;

&lt;p&gt;As applications grow, good organization becomes just as important as writing correct code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 — Run the Application
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
go run .&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Notice that we use &lt;code&gt;go run .&lt;/code&gt; instead of &lt;code&gt;go run main.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now test the API just as you did in the previous article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a task.&lt;/li&gt;
&lt;li&gt;Retrieve the list of tasks.&lt;/li&gt;
&lt;li&gt;Update a task.&lt;/li&gt;
&lt;li&gt;Delete a task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll notice that the API behaves exactly as before. The only difference is that the code is now organized into packages, making it easier to maintain as the project grows.&lt;/p&gt;

&lt;p&gt;Although we reorganized the code into packages, the application's behavior hasn't changed. We've simply made the project easier to understand and maintain.&lt;/p&gt;

&lt;p&gt;Once a project spans multiple files and packages, &lt;code&gt;go run .&lt;/code&gt; becomes the more natural command because it builds the entire module.&lt;/p&gt;

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

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>go</category>
      <category>backend</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a CRUD API in Go</title>
      <dc:creator>Steve Omollo</dc:creator>
      <pubDate>Thu, 16 Jul 2026 08:32:48 +0000</pubDate>
      <link>https://dev.to/steve_omollo/building-a-crud-api-in-go-37g0</link>
      <guid>https://dev.to/steve_omollo/building-a-crud-api-in-go-37g0</guid>
      <description>&lt;p&gt;Previously, we built a simple task API that could create and retrieve tasks.&lt;/p&gt;

&lt;p&gt;If you have been following this series, we've gradually progressed from building a simple HTTP server to creating a JSON-based task API. In this article, we will complete that progression by adding update and delete functionality, giving our API the four operations commonly known as CRUD.&lt;/p&gt;

&lt;p&gt;CRUD stands for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt;reate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;R&lt;/strong&gt;ead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;U&lt;/strong&gt;pdate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;D&lt;/strong&gt;elete&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These operations form the foundation of many backend applications and APIs.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will extend our task API using only Go's standard library. To keep things simple, we'll continue storing tasks in memory using a slice rather than a database.&lt;/p&gt;

&lt;p&gt;By the end, you'll understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how CRUD APIs work&lt;/li&gt;
&lt;li&gt;how to handle multiple HTTP methods&lt;/li&gt;
&lt;li&gt;how to update existing data&lt;/li&gt;
&lt;li&gt;how to remove data from slices&lt;/li&gt;
&lt;li&gt;how backend APIs manage resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go installed&lt;/li&gt;
&lt;li&gt;basic familiarity with Go syntax&lt;/li&gt;
&lt;li&gt;understanding of the &lt;code&gt;net/http&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;basic understanding of JSON handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can confirm if Go is installed by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1 — Create the Project
&lt;/h2&gt;

&lt;p&gt;Create a new folder for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;go-crud-api
&lt;span class="nb"&gt;cd &lt;/span&gt;go-crud-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now initialize a Go module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init go-crud-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2 — Create the Server File
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;main.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your project structure should now look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-crud-api/
├─ go.mod
└─ main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 — Write the CRUD API
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;main.go&lt;/code&gt; and add the following code:&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;        &lt;span class="kt"&gt;int&lt;/span&gt;        &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;     &lt;span class="s"&gt;`json:"title"`&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;tasks&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;tasksHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodGet&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPost&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;

        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPut&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;

        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;updatedTask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;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;task&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;tasks&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;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tasks&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;
                &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;return&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Task not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodDelete&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;taskToDelete&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;

        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;taskToDelete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;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;task&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;tasks&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;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;taskToDelete&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tasks&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="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task deleted"&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="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Task not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Method not allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusMethodNotAllowed&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tasksHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's unpack what is happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding CRUD Operations
&lt;/h2&gt;

&lt;p&gt;CRUD represents the four most common actions performed on data.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;HTTP Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create&lt;/td&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update&lt;/td&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete&lt;/td&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most backend APIs are built around these operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create and Read
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;GET&lt;/code&gt; handlers work exactly as they did in the previous tutorial.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST&lt;/code&gt; creates tasks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET&lt;/code&gt; retrieves tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These operations allow us to add and view data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Updates
&lt;/h3&gt;

&lt;p&gt;This section handles updates:&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;case&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPut&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server expects updated task information in the request body.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn Advanced Go"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After decoding the request, we search for a matching task:&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&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;tasks&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;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a match is found, we update the title:&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;tasks&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updatedTask&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we return the updated task as JSON.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Deletes
&lt;/h3&gt;

&lt;p&gt;This section handles deleting tasks:&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;case&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodDelete&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client sends the ID of the task to remove:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We search for the task with matching ID and remove it from the slice.&lt;/p&gt;

&lt;p&gt;The deletion happens here:&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;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tasks&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="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="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;This combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;everything before the task&lt;/li&gt;
&lt;li&gt;everything after the task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;into a new slice that no longer contains the deleted item.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Slice Deletion
&lt;/h3&gt;

&lt;p&gt;This line often looks strange at first:&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;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tasks&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="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="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;Let's break it down.&lt;/p&gt;

&lt;p&gt;Suppose we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tasks &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;1 2 3 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and want to remove:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then:&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;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;gives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&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;tasks&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="m"&gt;1&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;gives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;3 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Appending them together creates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;1 3 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The item has effectively been removed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Go Tip:&lt;/strong&gt; The &lt;code&gt;append(tasks[:i], tasks[i+1:]...)&lt;/code&gt; pattern is one of the most common ways to remove an element from a slice in Go. You'll see it in many Go projects, so it's worth understanding how it works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4 — Run the Server
&lt;/h2&gt;

&lt;p&gt;Start the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server should now be running on port &lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Create a Task
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/tasks &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"id":1,"title":"Learn Go"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn Go"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6 — Retrieve Tasks
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080/tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn Go"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7 — Update a Task
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT http://localhost:8080/tasks &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"id":1,"title":"Learn Advanced Go"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn Advanced Go"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8 — Delete a Task
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; DELETE http://localhost:8080/tasks &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"id":1}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Task deleted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens When a Request Is Made?
&lt;/h3&gt;

&lt;p&gt;Here's the flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client sends an HTTP request.&lt;/li&gt;
&lt;li&gt;Go checks the request method.&lt;/li&gt;
&lt;li&gt;The appropriate handler creates, retrieves, updates, or deletes a task.&lt;/li&gt;
&lt;li&gt;The server prepares the response.&lt;/li&gt;
&lt;li&gt;A response is sent back to the client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the foundation of many real-world APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to Go Next
&lt;/h3&gt;

&lt;p&gt;Now that we have a simple CRUD API, we could extend it by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;route parameters&lt;/li&gt;
&lt;li&gt;persistent databases&lt;/li&gt;
&lt;li&gt;request validation&lt;/li&gt;
&lt;li&gt;middleware&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where backend applications begin moving closer to production-ready systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;We started with a simple task API and extended it into a complete CRUD API.&lt;/p&gt;

&lt;p&gt;Along the way, we learned about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP methods&lt;/li&gt;
&lt;li&gt;updating data&lt;/li&gt;
&lt;li&gt;deleting data&lt;/li&gt;
&lt;li&gt;slice manipulation&lt;/li&gt;
&lt;li&gt;API design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concepts appear in countless backend applications and services.&lt;/p&gt;

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

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>go</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a Simple Task API in Go</title>
      <dc:creator>Steve Omollo</dc:creator>
      <pubDate>Mon, 01 Jun 2026 06:44:38 +0000</pubDate>
      <link>https://dev.to/steve_omollo/building-a-simple-task-api-in-go-2ceh</link>
      <guid>https://dev.to/steve_omollo/building-a-simple-task-api-in-go-2ceh</guid>
      <description>&lt;p&gt;Previously, we learned how to send and receive JSON data in Go.&lt;/p&gt;

&lt;p&gt;One of the next steps in building backend applications is creating APIs with multiple endpoints that can handle different types of requests.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will build a simple task API in Go using only the standard library.&lt;/p&gt;

&lt;p&gt;By the end, you will understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how API endpoints work&lt;/li&gt;
&lt;li&gt;how to handle multiple HTTP methods&lt;/li&gt;
&lt;li&gt;how to store data in memory using slices&lt;/li&gt;
&lt;li&gt;how to send and receive JSON data&lt;/li&gt;
&lt;li&gt;how backend APIs manage resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go installed&lt;/li&gt;
&lt;li&gt;basic familiarity with Go syntax&lt;/li&gt;
&lt;li&gt;understanding of the &lt;code&gt;net/http&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;basic understanding of JSON handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can confirm if Go is installed by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1 — Create the Project
&lt;/h2&gt;

&lt;p&gt;Create a new folder for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;go-task-api
&lt;span class="nb"&gt;cd &lt;/span&gt;go-task-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now initialize a Go module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init go-task-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;go.mod&lt;/code&gt; file for managing project dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Create the Server File
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;main.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your project structure should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-task-api/
├─ go.mod
└─ main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 — Write the API
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;main.go&lt;/code&gt; and add the following code:&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"title"`&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;tasks&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;tasksHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodGet&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPost&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;

        &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Method not allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusMethodNotAllowed&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tasksHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's unpack what is happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Struct
&lt;/h2&gt;

&lt;p&gt;This struct represents a task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"title"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each task contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an &lt;code&gt;ID&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;Title&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This struct defines the JSON format our API will use.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn Go"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Understanding In-Memory Storage
&lt;/h2&gt;

&lt;p&gt;This line:&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;var&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;creates a slice that stores tasks in memory.&lt;/p&gt;

&lt;p&gt;For now, our data only exists while the server is running.&lt;/p&gt;

&lt;p&gt;Once the server stops, the data disappears.&lt;/p&gt;

&lt;p&gt;This keeps the tutorial simple before introducing databases later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding HTTP Methods
&lt;/h2&gt;

&lt;p&gt;This part checks the request method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HTTP methods tell the server what action the client wants to perform.&lt;/p&gt;

&lt;p&gt;Here, we handle:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieves tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Later, we could also add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PUT&lt;/code&gt; for updating tasks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE&lt;/code&gt; for removing tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because, you know, every backend journey eventually leads there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling GET Requests
&lt;/h2&gt;

&lt;p&gt;This section handles fetching tasks:&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;case&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodGet&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the client sends a &lt;code&gt;GET&lt;/code&gt; request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the server retrieves all tasks&lt;/li&gt;
&lt;li&gt;the tasks are converted into JSON&lt;/li&gt;
&lt;li&gt;the JSON response is sent back to the client&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Handling POST Requests
&lt;/h2&gt;

&lt;p&gt;This section handles creating tasks:&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;case&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MethodPost&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside this block:&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;var&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we create a task variable to store the incoming JSON data.&lt;/p&gt;

&lt;p&gt;Then we decode the request body:&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If decoding succeeds, we add the task to the slice:&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;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&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 return the created task as JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding &lt;code&gt;append&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This line:&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;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;adds a new task to the slice.&lt;/p&gt;

&lt;p&gt;Slices in Go are dynamic, that is, they can grow as we add more data.&lt;/p&gt;

&lt;p&gt;This allows our API to store multiple tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Error Handling
&lt;/h2&gt;

&lt;p&gt;This section checks whether the JSON request is valid:&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;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;If decoding fails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the server sends an error response&lt;/li&gt;
&lt;li&gt;the request stops processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps keep the API stable when invalid data is sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Run the Server
&lt;/h2&gt;

&lt;p&gt;Start the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server should now be running on port &lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Create a Task
&lt;/h2&gt;

&lt;p&gt;We can create a task using &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/tasks &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"id":1,"title":"Learn Go"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn Go"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6 — Retrieve Tasks
&lt;/h2&gt;

&lt;p&gt;Now retrieve all tasks using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080/tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn Go"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Happens When a Request Is Made?
&lt;/h2&gt;

&lt;p&gt;Here's the flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client sends an HTTP request&lt;/li&gt;
&lt;li&gt;Go checks the request method&lt;/li&gt;
&lt;li&gt;The correct code block runs&lt;/li&gt;
&lt;li&gt;Tasks are created or retrieved&lt;/li&gt;
&lt;li&gt;JSON responses are returned to the client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the foundation of many backend APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Go Next
&lt;/h2&gt;

&lt;p&gt;Now that we have a simple task API, we could extend it by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PUT requests&lt;/li&gt;
&lt;li&gt;DELETE requests&lt;/li&gt;
&lt;li&gt;route parameters&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;request validation&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where backend applications start becoming much more powerful and realistic.&lt;/p&gt;

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

&lt;p&gt;We started with simple HTTP servers and gradually built a working task API.&lt;/p&gt;

&lt;p&gt;Along the way, we learned about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP methods&lt;/li&gt;
&lt;li&gt;JSON encoding&lt;/li&gt;
&lt;li&gt;JSON decoding&lt;/li&gt;
&lt;li&gt;slices&lt;/li&gt;
&lt;li&gt;request handling&lt;/li&gt;
&lt;li&gt;API design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the foundational backend development concepts that appear in many real-world applications.&lt;/p&gt;

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

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>go</category>
      <category>backend</category>
      <category>json</category>
      <category>api</category>
    </item>
    <item>
      <title>Handling JSON Requests in Go</title>
      <dc:creator>Steve Omollo</dc:creator>
      <pubDate>Sat, 23 May 2026 11:59:27 +0000</pubDate>
      <link>https://dev.to/steve_omollo/handling-json-requests-in-go-23mc</link>
      <guid>https://dev.to/steve_omollo/handling-json-requests-in-go-23mc</guid>
      <description>&lt;p&gt;Previously, we learned how to return JSON responses from a Go server.&lt;/p&gt;

&lt;p&gt;But APIs do not only send data — they also receive it.&lt;/p&gt;

&lt;p&gt;Frontend applications, mobile apps, and clients commonly send JSON data to servers through HTTP requests.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will learn how to handle JSON requests in Go by decoding request bodies into structs using Go's standard library.&lt;/p&gt;

&lt;p&gt;By the end, you will understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how JSON request bodies work&lt;/li&gt;
&lt;li&gt;how to decode JSON in Go&lt;/li&gt;
&lt;li&gt;how POST requests work&lt;/li&gt;
&lt;li&gt;how to process incoming client data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go installed&lt;/li&gt;
&lt;li&gt;basic familiarity with Go syntax&lt;/li&gt;
&lt;li&gt;understanding of the &lt;code&gt;net/http&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;basic understanding of JSON responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can confirm if Go is installed by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1 — Create the Project
&lt;/h2&gt;

&lt;p&gt;Create a new folder for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;go-json-requests
&lt;span class="nb"&gt;cd &lt;/span&gt;go-json-requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now initialize a Go module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init go-json-requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;go.mod&lt;/code&gt; file for managing project dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Create the Server File
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;main.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your project structure should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-json-requests/
├─ go.mod
└─ main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 — Write the Server
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;main.go&lt;/code&gt; and add the following code:&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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"name"`&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;userHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;user&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, %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;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userHandler&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;"Server running on :8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's unpack what is happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding POST Requests
&lt;/h2&gt;

&lt;p&gt;In the previous examples, we mainly worked with routes that returned data.&lt;/p&gt;

&lt;p&gt;This time, the client sends data to the server.&lt;/p&gt;

&lt;p&gt;This commonly happens using a &lt;code&gt;POST&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;POST requests are used when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;submitting forms&lt;/li&gt;
&lt;li&gt;sending JSON data&lt;/li&gt;
&lt;li&gt;creating resources&lt;/li&gt;
&lt;li&gt;uploading information to a server&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding the Struct
&lt;/h2&gt;

&lt;p&gt;This struct defines the shape of the JSON data we expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"name"`&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 client sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Steve"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go can decode that JSON into the struct.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;json:"name"&lt;/code&gt; tag tells Go which JSON field maps to the struct field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Request Bodies
&lt;/h2&gt;

&lt;p&gt;When a client sends data to a server, the data is stored inside the request body.&lt;/p&gt;

&lt;p&gt;In Go, we access it using:&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;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Body&lt;/code&gt; contains the incoming JSON data from the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decoding JSON Requests
&lt;/h2&gt;

&lt;p&gt;This line is the heart of the server:&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NewDecoder(r.Body)&lt;/code&gt; reads the incoming request body&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Decode(&amp;amp;user)&lt;/code&gt; converts the JSON into the struct&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;user&lt;/code&gt; passes a pointer so Go can modify the struct value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After decoding, the &lt;code&gt;user&lt;/code&gt; variable contains the client data.&lt;/p&gt;

&lt;h2&gt;
  
  
  So Why Do We Use &lt;code&gt;&amp;amp;user&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;You may notice this part:&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;amp;&lt;/code&gt; symbol means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Use the memory address of this variable."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The decoder needs direct access to the struct so it can fill in the fields with incoming JSON data.&lt;/p&gt;

&lt;p&gt;Without the pointer, decoding would not work correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Error Handling
&lt;/h2&gt;

&lt;p&gt;This section checks whether the JSON request is valid:&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;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid JSON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&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;If decoding fails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the server sends an error response&lt;/li&gt;
&lt;li&gt;the request stops processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps prevent invalid client data from crashing the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Run the Server
&lt;/h2&gt;

&lt;p&gt;Start the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server running on :8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 — Test the API
&lt;/h2&gt;

&lt;p&gt;This server expects a POST request containing JSON data.&lt;/p&gt;

&lt;p&gt;We can test it using &lt;code&gt;curl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/user &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name":"Steve"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello, Steve!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Happens When a Request Is Made?
&lt;/h2&gt;

&lt;p&gt;Here's the flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client sends a POST request&lt;/li&gt;
&lt;li&gt;JSON data is placed inside the request body&lt;/li&gt;
&lt;li&gt;Go reads the request body&lt;/li&gt;
&lt;li&gt;The JSON is decoded into a struct&lt;/li&gt;
&lt;li&gt;The server processes the data&lt;/li&gt;
&lt;li&gt;A response is sent back to the client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the foundation of many real-world APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Go Next
&lt;/h2&gt;

&lt;p&gt;Now that we can decode JSON requests, we could extend this server by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multiple API endpoints&lt;/li&gt;
&lt;li&gt;JSON responses&lt;/li&gt;
&lt;li&gt;CRUD operations — again, because every backend journey eventually leads there&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;request validation&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where backend development starts becoming much more interactive and dynamic.&lt;/p&gt;

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

&lt;p&gt;We started with a simple server that only returned data.&lt;/p&gt;

&lt;p&gt;Now our server can also receive and process JSON requests from clients.&lt;/p&gt;

&lt;p&gt;Along the way, we learned about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;POST requests&lt;/li&gt;
&lt;li&gt;request bodies&lt;/li&gt;
&lt;li&gt;JSON decoding&lt;/li&gt;
&lt;li&gt;structs&lt;/li&gt;
&lt;li&gt;pointers&lt;/li&gt;
&lt;li&gt;error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concepts are essential when building APIs in Go.&lt;/p&gt;

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

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>go</category>
      <category>json</category>
    </item>
    <item>
      <title>Returning JSON Responses in Go</title>
      <dc:creator>Steve Omollo</dc:creator>
      <pubDate>Fri, 15 May 2026 20:10:30 +0000</pubDate>
      <link>https://dev.to/steve_omollo/returning-json-responses-in-go-16bk</link>
      <guid>https://dev.to/steve_omollo/returning-json-responses-in-go-16bk</guid>
      <description>&lt;p&gt;In the previous tutorial, we built a simple HTTP server in Go that returned plain text responses.&lt;/p&gt;

&lt;p&gt;While that works, most modern applications communicate using JSON.&lt;/p&gt;

&lt;p&gt;Frontend applications, mobile apps, and APIs commonly exchange data in JSON format.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will learn how to return JSON responses from a Go server using Go's standard library.&lt;/p&gt;

&lt;p&gt;By the end, you will understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how JSON responses work in Go&lt;/li&gt;
&lt;li&gt;how to create structs&lt;/li&gt;
&lt;li&gt;how to encode data into JSON&lt;/li&gt;
&lt;li&gt;how to send JSON from an HTTP server&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go installed&lt;/li&gt;
&lt;li&gt;basic familiarity with Go syntax&lt;/li&gt;
&lt;li&gt;understanding of the &lt;code&gt;net/http&lt;/code&gt; package&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can confirm if Go is installed by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1 — Create the Project
&lt;/h2&gt;

&lt;p&gt;Create a new folder for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;go-json-server
&lt;span class="nb"&gt;cd &lt;/span&gt;go-json-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now initialize a Go module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init go-json-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;go.mod&lt;/code&gt; file for managing project dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Create the Server File
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;main.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your project structure should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-json-server/
├── go.mod
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 — Write the JSON Server
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;main.go&lt;/code&gt; and write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;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;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"text"`&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;homeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello from Go!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;homeHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's unpack what is happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Imports
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We imported two packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;net/http&lt;/code&gt; — used for creating the HTTP server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;encoding/json&lt;/code&gt; — used for converting Go data into JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;encoding/json&lt;/code&gt; package is part of Go's standard library, so we do not need to install anything extra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Structs
&lt;/h2&gt;

&lt;p&gt;This part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"text"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;defines a struct.&lt;/p&gt;

&lt;p&gt;Structs are used to group related data together.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Message&lt;/code&gt; is the struct name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Text&lt;/code&gt; is a field inside the struct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We later use this struct to create JSON responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is &lt;code&gt;Text&lt;/code&gt; Capitalized?
&lt;/h3&gt;

&lt;p&gt;You may notice that &lt;code&gt;Text&lt;/code&gt; starts with an uppercase letter.&lt;/p&gt;

&lt;p&gt;In Go, fields must begin with uppercase letters to be exported.&lt;/p&gt;

&lt;p&gt;The JSON encoder can only access exported fields.&lt;/p&gt;

&lt;p&gt;For example, this would not work correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because &lt;code&gt;text&lt;/code&gt; is unexported.&lt;/p&gt;

&lt;p&gt;This is a very important concept when working with JSON in Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding JSON Tags
&lt;/h2&gt;

&lt;p&gt;This part:&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="s"&gt;`json:"text"`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is called a JSON tag.&lt;/p&gt;

&lt;p&gt;JSON tags control how fields appear in the JSON response.&lt;/p&gt;

&lt;p&gt;Our Go field is named:&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;Text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but the JSON output becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from Go!"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to keep Go naming conventions while returning clean JSON responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Response Headers
&lt;/h2&gt;

&lt;p&gt;Inside the handler, we set a response header:&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;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Headers provide additional information about the HTTP response.&lt;/p&gt;

&lt;p&gt;Here, we tell the client:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This response contains JSON data."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is standard practice when building APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Response Data
&lt;/h2&gt;

&lt;p&gt;Inside the handler, we create a struct value:&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;response&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello from Go!"&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 creates the data we want to send back to the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encoding JSON Responses
&lt;/h2&gt;

&lt;p&gt;This line converts the Go struct into JSON:&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NewEncoder(w)&lt;/code&gt; creates a JSON encoder&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;w&lt;/code&gt; represents the HTTP response&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Encode(response)&lt;/code&gt; converts the struct into JSON and sends it to the client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of the most common ways to return JSON in Go web servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Run the Server
&lt;/h2&gt;

&lt;p&gt;Start the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server should now be running on port &lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Test the Server
&lt;/h2&gt;

&lt;p&gt;Open your browser and visit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from Go!"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing with curl
&lt;/h2&gt;

&lt;p&gt;You can also test the server from the terminal using &lt;code&gt;curl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from Go!"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens When a Request Is Made?
&lt;/h3&gt;

&lt;p&gt;Here's the flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client sends an HTTP request&lt;/li&gt;
&lt;li&gt;Go matches the route&lt;/li&gt;
&lt;li&gt;The handler function runs&lt;/li&gt;
&lt;li&gt;A struct is created&lt;/li&gt;
&lt;li&gt;The struct is converted into JSON&lt;/li&gt;
&lt;li&gt;The JSON response is sent back to the client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the foundation of many backend APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Go Next
&lt;/h2&gt;

&lt;p&gt;Now that we can return JSON responses, we could extend this server by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multiple API routes&lt;/li&gt;
&lt;li&gt;dynamic JSON responses&lt;/li&gt;
&lt;li&gt;request body handling&lt;/li&gt;
&lt;li&gt;JSON decoding&lt;/li&gt;
&lt;li&gt;CRUD operations — because, you know, every backend journey eventually leads there&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where backend development starts becoming more interactive and powerful.&lt;/p&gt;

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

&lt;p&gt;We started with a plain text HTTP server, evolved it into a simple JSON API.&lt;/p&gt;

&lt;p&gt;Along the way, we learned about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;structs&lt;/li&gt;
&lt;li&gt;JSON encoding&lt;/li&gt;
&lt;li&gt;response headers&lt;/li&gt;
&lt;li&gt;API responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concepts form the foundation of modern backend development in Go.&lt;/p&gt;

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

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>go</category>
      <category>backend</category>
      <category>api</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building a Simple Web Server in Go</title>
      <dc:creator>Steve Omollo</dc:creator>
      <pubDate>Wed, 13 May 2026 09:29:31 +0000</pubDate>
      <link>https://dev.to/steve_omollo/building-a-simple-web-server-in-go-59hl</link>
      <guid>https://dev.to/steve_omollo/building-a-simple-web-server-in-go-59hl</guid>
      <description>&lt;p&gt;Have you ever wondered how web servers work behind the scenes?&lt;/p&gt;

&lt;p&gt;One of the best things about Go is that you can create a working HTTP server with a few lines of code. The standard library already gives us everything we need to start serving web requests without installing any frameworks.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will be building a simple web server in Go that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;listens on port &lt;code&gt;8080&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;responds to browser requests&lt;/li&gt;
&lt;li&gt;serves different routes&lt;/li&gt;
&lt;li&gt;returns simple text responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you will understand the basics of how Go handles HTTP requests and responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go installed&lt;/li&gt;
&lt;li&gt;basic familiarity with the terminal&lt;/li&gt;
&lt;li&gt;beginner-level Go syntax knowledge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can confirm if Go is installed by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1 — Create the Project
&lt;/h2&gt;

&lt;p&gt;Create a new folder for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;simple-go-server
&lt;span class="nb"&gt;cd &lt;/span&gt;simple-go-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now initialize a Go module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init simple-go-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;go.mod&lt;/code&gt; file that helps Go manage dependencies for the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Create the Server File
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;main.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your project should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;simple-go-server/
├── go.mod
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 — Write the HTTP Server
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;main.go&lt;/code&gt; and add the following code:&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;"net/http"&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;homeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello from Go!"&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;aboutHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"This is the about page."&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;homeHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aboutHandler&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;"Server running on :8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error starting server:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's unpack this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Imports
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&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;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We imported two packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fmt&lt;/code&gt; - is used for printing messages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;net/http&lt;/code&gt; - is Go's built-in package for creating HTTP servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;net/http&lt;/code&gt; package is part of Go's standard library, which means we don't need to install anything extra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Handlers
&lt;/h2&gt;

&lt;p&gt;This function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;homeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is called a &lt;strong&gt;handler&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Handlers are functions that respond to incoming HTTP requests.&lt;/p&gt;

&lt;p&gt;The parameters mean:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Parameter&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http.ResponseWriter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Used to send data back to the client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*http.Request&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Contains information about the incoming request&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Inside the handler, we write a response:&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello from Go!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sends text back to the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Routes
&lt;/h2&gt;

&lt;p&gt;Here:&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;homeHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we tell Go:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"When someone visits &lt;code&gt;/&lt;/code&gt;, run the &lt;code&gt;homeHandler&lt;/code&gt; function."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And here:&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aboutHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we register another route.&lt;/p&gt;

&lt;p&gt;Now our server has two endpoints:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Route&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hello from Go!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/about&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This is the about page.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After registering routes, the final step is starting the server and listening for incoming requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting the Server
&lt;/h2&gt;

&lt;p&gt;This line starts the web server:&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;:8080&lt;/code&gt; means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Listen for incoming requests on port 8080."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;nil&lt;/code&gt; tells Go to use the default request multiplexer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Run the Server
&lt;/h2&gt;

&lt;p&gt;Start the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server running on :8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 — Test the Server
&lt;/h2&gt;

&lt;p&gt;Open your browser and visit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&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 Go!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080/about
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This is the about page.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing with curl
&lt;/h2&gt;

&lt;p&gt;You can also test the server from the terminal using &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the home route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the about route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl localhost:8080/about
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Here's basically what happens when you visit a route:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your browser sends an HTTP request&lt;/li&gt;
&lt;li&gt;Go receives the request&lt;/li&gt;
&lt;li&gt;Go checks which route matches&lt;/li&gt;
&lt;li&gt;The correct handler runs&lt;/li&gt;
&lt;li&gt;A response is sent back to the browser&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the foundation of most backend web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Go Next
&lt;/h2&gt;

&lt;p&gt;Our server is very simple, but from here you could add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON responses&lt;/li&gt;
&lt;li&gt;HTML templates&lt;/li&gt;
&lt;li&gt;middleware&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;REST APIs — because eventually, everyone builds one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one reason many developers enjoy Go for backend development — you can start small and gradually build more complex systems while keeping the code readable.&lt;/p&gt;

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

&lt;p&gt;Go makes it incredibly easy to get started with backend development.&lt;/p&gt;

&lt;p&gt;With a few lines of code, we created a working HTTP server capable of handling multiple routes and serving responses to clients.&lt;/p&gt;

&lt;p&gt;If you are learning backend development, understanding the &lt;code&gt;net/http&lt;/code&gt; package is a great foundation before moving into larger frameworks and architectures.&lt;/p&gt;

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

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
