<?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: Ezeana Micheal</title>
    <description>The latest articles on DEV Community by Ezeana Micheal (@ezeanamichael).</description>
    <link>https://dev.to/ezeanamichael</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%2F795718%2F32ca5ddb-abe1-44e1-9391-85534fc496af.jpg</url>
      <title>DEV Community: Ezeana Micheal</title>
      <link>https://dev.to/ezeanamichael</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ezeanamichael"/>
    <language>en</language>
    <item>
      <title>The Bilingual Developer: Python and Go Core Functions</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 19 Jun 2026 18:32:56 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-core-functions-3045</link>
      <guid>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-core-functions-3045</guid>
      <description>&lt;h1&gt;
  
  
  The Bilingual Developer: Python and Go Core Functions
&lt;/h1&gt;

&lt;p&gt;So far in our journey, we have explored the building blocks of programming:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How to store data using variables,
&lt;/li&gt;
&lt;li&gt;How to guide the flow of execution using conditional statements, and
&lt;/li&gt;
&lt;li&gt;How to repeat actions efficiently using loops.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These tools are enough to write simple scripts that can process data or automate mundane tasks.&lt;/p&gt;

&lt;p&gt;However, as you start to write larger, more ambitious applications, a new and significant challenge emerges. Imagine you are building an e-commerce platform. You will need the logic for calculating prices based on complex discount rules, validating user credentials against a database, sending transactional emails, and even securely processing credit card payments.&lt;/p&gt;

&lt;p&gt;If you try to cram all of this functionality into one massive, linear/sequential file, the code quickly descends into what developers affectionately refer to as "spaghetti code." The logic becomes intertwined, variables conflict with each other, and making a single change to a pricing rule might unexpectedly break the email system. Tracking down a single bug in a 10,000-line file becomes a detective's nightmare, and collaborating with other developers becomes nearly impossible.&lt;/p&gt;

&lt;p&gt;This is precisely where &lt;strong&gt;functions&lt;/strong&gt; come into play. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Functions?
&lt;/h2&gt;

&lt;p&gt;A function allows us to encapsulate a specific piece of logic into an independent, reusable, and named block of code. We can define the logic once and then "call" it whenever we need that specific behavior.&lt;/p&gt;

&lt;p&gt;Think of a function like a specialized machine on an assembly line. You place raw materials at the entrance (these are the &lt;strong&gt;inputs&lt;/strong&gt; or parameters). The gears and motors inside turn and process those materials (this is the internal &lt;strong&gt;processing&lt;/strong&gt;). Finally, a finished product rolls out at the end (this is the &lt;strong&gt;return value&lt;/strong&gt;). &lt;/p&gt;

&lt;p&gt;For example, consider a calculator function: the input would be the numbers and the operation (e.g., 5 + 10), the processing would be the internal addition logic, and the output would be the answer (15). This separation between the "how" (the internal mechanics) and the "what" (the input/output) is what makes functions so powerful.&lt;/p&gt;

&lt;p&gt;Both Python and Go rely heavily on functions, but once again, the way they define, structure, and treat these functions showcases a fundamental difference in the philosophies of the two languages.&lt;/p&gt;

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

&lt;p&gt;At its core, a function is a reusable block of code designed to perform a single, specific task. Think of it as a verb in your program; it acts.&lt;br&gt;&lt;br&gt;
Instead of writing the same code repeatedly, like manually printing a welcome message for each user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome Michael&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome Sarah&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Welcome David&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can create a function named welcome_user() and simply reuse that one-liner over and over again.&lt;/p&gt;

&lt;p&gt;This simple abstraction provides benefits to software development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoiding Repetition (DRY Principle)&lt;/strong&gt;: Standing for &lt;em&gt;Don't Repeat Yourself&lt;/em&gt;, this is a core tenet of software engineering. If you need to change the welcome message from "Welcome" to "Greetings", you only need to change the code inside the function once, rather than searching through hundreds of files.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Organization&lt;/strong&gt;: Functions allow you to break a massive, monolithic program into small, digestible, logical modules. You can group related tasks together (e.g., putting all user authentication logic into a single file of functions).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Debugging&lt;/strong&gt;: When a bug occurs, functions help isolate the problem. If the pricing calculation is wrong, you know exactly which function to inspect without sifting through irrelevant code for user validation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable Components&lt;/strong&gt;: Once you write a function, you can use it in different parts of your application, or even copy it into a completely different project, saving precious development time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Anatomy of Function Definition
&lt;/h2&gt;

&lt;p&gt;The very first difference we encounter between Python and Go is the syntax required to &lt;em&gt;declare&lt;/em&gt; a function to the compiler or interpreter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python: Using def
&lt;/h3&gt;

&lt;p&gt;Python prides itself on readability, and its function definition syntax is an excellent example. It uses the straightforward keyword def, which is an abbreviation for "define."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello Developer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To execute this function, you simply call it by its name followed by parentheses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;We can notice how Python's structure almost reads like plain English: &lt;em&gt;Define a function called greet.&lt;/em&gt; Furthermore, Python does not use brackets to define the scope of the function. Instead, it strictly relies on &lt;strong&gt;indentation&lt;/strong&gt;(as we have seen in loops and conditions too). The indented block of code directly underneath the def statement is what belongs to the function. This forces clean, uniform formatting across all Python code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go: Using func
&lt;/h3&gt;

&lt;p&gt;Go takes a slightly more terse, brace-oriented approach. It uses the keyword func to declare a 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;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello Developer"&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;Calling the function is syntactically similar to Python:&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;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;However, the structural differences are immediately apparent. Go uses curly braces { } to define the beginning and end of the function's logic, much like C, Java, or JavaScript. Additionally, Go is strict about syntax; the opening curly brace &lt;strong&gt;must&lt;/strong&gt; be on the same line as the function declaration, otherwise, the compiler will throw an error. While Python relies on the developer to maintain consistent whitespace, Go offloads that structural enforcement to the compiler using braces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing Information: Functions With Parameters
&lt;/h2&gt;

&lt;p&gt;Most functions are not meant to do the exact same thing every single time. They need dynamic information to work with. For instance, instead of creating a function that always prints "Hello Michael", we want a function that works for anyone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Parameters
&lt;/h3&gt;

&lt;p&gt;Python allows you to define parameters inside the parentheses. Because Python is dynamically typed, you just provide the variable name without specifying what &lt;em&gt;kind&lt;/em&gt; of data it is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you call this function, you pass the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Michael&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;Python's approach emphasizes flexibility. You can pass a string, an integer, or even a list into that name parameter. While this is convenient, it means the interpreter will only realize you passed a wrong type (like a number that breaks the print formatting) when the code is actually running. Although in newer versions of python you can specify a type hint to specify datatype, see more below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go Parameters
&lt;/h3&gt;

&lt;p&gt;Go, on the other hand, requires explicit type declarations. When defining the function, you must tell the compiler exactly what data type the name parameter is expected to hold.&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;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The name string part is mandatory. It tells Go: &lt;em&gt;"This function expects a single argument called 'name', and it must strictly be a string."&lt;/em&gt; Calling the function remains the same:&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;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Michael"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This requirement ensures that the Go compiler knows exactly how much memory to allocate for the variable and prevents you from accidentally passing an integer to a function that expects text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Function Signatures
&lt;/h2&gt;

&lt;p&gt;In computer science, a &lt;strong&gt;function signature&lt;/strong&gt; acts as the "contract" of a function. It defines the function's name, the types and order of its parameters, and the types of values it returns. This is where Python and Go fundamentally diverge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python: Optional Type Hints
&lt;/h3&gt;

&lt;p&gt;Python operates on dynamic typing. By default, Python does not care about the data types, so a signature is simply the name and parameter list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interpreter figures out what a and b are only when the function runs.&lt;br&gt;&lt;br&gt;
However, Python 3 introduced "Type Hints" to add optional clarity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we communicate our intention: a and b should be integers, and the output should be an integer. This is fantastic for documentation and helps IDEs catch potential issues. &lt;strong&gt;Crucially, however, Python does not enforce these hints&lt;/strong&gt;. You could still write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the context, this might run perfectly fine (it would concatenate the strings) or crash. The responsibility lies entirely with the developer and third-party tools like mypy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go: Mandatory Types
&lt;/h3&gt;

&lt;p&gt;Go is a statically typed language. Types are not optional; they are part of the language's DNA. The function signature is explicitly defined:&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;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the signature is rigid and unmistakable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inputs&lt;/strong&gt;: a (int) and b (int).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output&lt;/strong&gt;: int.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Go compiler rigorously checks these type definitions during the &lt;em&gt;compilation phase&lt;/em&gt;, which happens before the code ever runs. This is known as compile-time safety. Consequently, if you try to compile add("Hello", "World"), the compiler will halt and refuse to build the executable, throwing a type mismatch error instantly.&lt;/p&gt;

&lt;p&gt;This difference highlights the core philosophies: Python acts like a flexible workshop where you can modify things quickly with few restrictions, while Go acts like a precision engineering lab where everything must be measured and declared upfront to prevent catastrophic failures later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Returning Data
&lt;/h2&gt;

&lt;p&gt;Most functions are designed not just to perform an action but to compute a result and hand it back to the part of the program that called them. For example, a calculator function isn't helpful if it just calculates internally and throws the answer away; it must return the answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python: Returning Values
&lt;/h3&gt;

&lt;p&gt;Python uses the return keyword to send data back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Output: 15  
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While Python appears to support returning multiple values, it actually does so using a trick. When you write return "Michael", 25, Python is internally creating a tuple and returning that single container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_info&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Michael&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;

&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;user_info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# This is tuple unpacking  
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function didn't natively return two separate things; it returned one tuple, and Python gracefully unpacked it into two variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go: Native Multiple Return Values
&lt;/h3&gt;

&lt;p&gt;Go has native support for returning multiple distinct values directly from the function, without wrapping them in a container.&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;userInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Michael"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;userInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="c"&gt;// name is now "Michael", age is now 25  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The (string, int) part of the signature explicitly declares that this function will produce two separate values. This is a language-level feature, not a trick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Multiple Returns Are a Game-Changer in Go
&lt;/h2&gt;

&lt;p&gt;The native support for multiple return values isn't just a syntactic convenience; it fundamentally shapes how Go handles errors.&lt;/p&gt;

&lt;p&gt;In many other languages (including Python), errors are often handled using try/except blocks. These exceptions can be thrown deep inside a function and caught elsewhere, potentially leading to situations where a developer forgets to catch an error entirely, causing the program to crash unpredictably.&lt;/p&gt;

&lt;p&gt;Go takes a radically different approach. It discourages exceptions in favor of explicit error handling. The most idiomatic pattern in Go is to return &lt;strong&gt;two values&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The actual result (if successful).
&lt;/li&gt;
&lt;li&gt;An error value (if something went wrong).
&lt;/li&gt;
&lt;/ol&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;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cannot divide by zero"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="c"&gt;// nil means "no error"  &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you call this function, you are forced to immediately acknowledge both the result and the possibility of an error:&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;result&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;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&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;"Oops:"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Result:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&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 pattern appears everywhere in Go. It forces the developer to confront the possibility of failure right at the point of execution, leading to more robust, predictable software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python vs. Go: The Underlying Philosophies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Python's Angle:&lt;/strong&gt; Python focuses on developer velocity and flexibility. It uses def, treats types as optional enhancements, and allows functions to accept a variety of data without strict declarations. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go's Angle:&lt;/strong&gt; Go focuses on clarity, maintainability, and safety. It uses func, mandates types, and ensures that the inputs and outputs of every function are crystal clear to both the developer and the compiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Mastering functions is an exciting leap in the programming journey. It marks the transition from writing small, disposable scripts to architecting real, maintainable applications. Functions allow you to take complex, tangled logic and break it down into small, reusable pieces.&lt;/p&gt;

&lt;p&gt;A Python developer moving to Go might initially feel constrained, asking, &lt;em&gt;"Why do I have to write all these types and explicitly handle every error?"&lt;/em&gt;     &lt;/p&gt;

&lt;p&gt;I felt this way before, and honestly, its worth it. This constraint is a feature, not a bug. Go pushes you to clearly articulate how data moves through your program, ensuring you understand the flow of information thoroughly before the code even runs. Learning to appreciate this enforced clarity doesn't just make you better at Go; it fundamentally sharpens your discipline as a developer. It trains you to think critically about data flow and architecture, a skill that is invaluable regardless of which language you ultimately choose to write your applications in.&lt;/p&gt;

&lt;p&gt;Thanks for reaching the end of my article, like, comment and share, lets keep-on our journey dual-learning.  &lt;/p&gt;

</description>
      <category>python</category>
      <category>go</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Go's Goroutines Made Concurrency Finally Click for Me</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 19 Jun 2026 18:12:27 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/why-gos-goroutines-made-concurrency-finally-click-for-me-n9e</link>
      <guid>https://dev.to/ezeanamichael/why-gos-goroutines-made-concurrency-finally-click-for-me-n9e</guid>
      <description>&lt;p&gt;I’ve been writing Python for a long time, and like many developers in that space, I got used to a certain way of thinking about concurrency: async/await, event loops, and carefully managing when things pause and resume. It worked well but sometimes it felt like I was always negotiating with the runtime instead of just expressing what I actually want: “run these things at the same time.”&lt;br&gt;&lt;br&gt;
Then I started studying Go (programming language), and specifically goroutines.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Python Mental Model: Concurrency as Coordination
&lt;/h2&gt;

&lt;p&gt;In Python, especially with asyncio, concurrency often feels like structured waiting. With Python (programming language), you typically deal with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An event loop
&lt;/li&gt;
&lt;li&gt;async functions
&lt;/li&gt;
&lt;li&gt;await points that explicitly yield control
&lt;/li&gt;
&lt;li&gt;Tasks that must cooperate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t just “run things at the same time.” You define where they can pause.&lt;br&gt;&lt;br&gt;
That design is nice, especially for I/O-heavy workloads. But mentally, there’s always overhead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where do I await?
&lt;/li&gt;
&lt;li&gt;Am I blocking the loop?
&lt;/li&gt;
&lt;li&gt;Why isn’t this coroutine running?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even when you understand it, concurrency still feels like something you carefully orchestrate.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enter Goroutines: Concurrency as a Default State
&lt;/h2&gt;

&lt;p&gt;Then I met goroutines. A goroutine is deceptively simple:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;go doSomething()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That’s it, no need for an async keyword, event loop management or even explicit suspension points. The runtime handles scheduling. You don’t coordinate concurrency, you declare it.&lt;br&gt;&lt;br&gt;
At first, this feels almost too simple. But that’s the shift: Go already made the hard decisions for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Mental Shift: From Await Points to Independent Workers
&lt;/h2&gt;

&lt;p&gt;To illustrate, Python async feels like a single chef multitasking in one kitchen. Go feels like hiring multiple cooks.&lt;br&gt;&lt;br&gt;
In Python:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One worker switches tasks
&lt;/li&gt;
&lt;li&gt;You define pause points
&lt;/li&gt;
&lt;li&gt;Everything shares a single execution flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Go:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each goroutine is a worker
&lt;/li&gt;
&lt;li&gt;Tasks run independently
&lt;/li&gt;
&lt;li&gt;You just assign work and move on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That difference is why goroutines clicked: they match how systems feel in real life, not how we simulate them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Async vs Go: Pros and Cons
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Python Async (async/await)
&lt;/h3&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very explicit control over execution flow
&lt;/li&gt;
&lt;li&gt;Excellent for structured I/O concurrency (web servers, APIs)
&lt;/li&gt;
&lt;li&gt;Easier debugging in some cases (you can trace await chains)
&lt;/li&gt;
&lt;li&gt;Fine-grained control over when tasks yield&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires careful mental tracking of the event loop
&lt;/li&gt;
&lt;li&gt;“Async all the way down” problem (one blocking call breaks everything)
&lt;/li&gt;
&lt;li&gt;More boilerplate and discipline required
&lt;/li&gt;
&lt;li&gt;Easy to accidentally mix sync + async and create issues
&lt;/li&gt;
&lt;li&gt;Concurrency feels manual rather than natural&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Go Goroutines
&lt;/h3&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extremely simple syntax (go function())
&lt;/li&gt;
&lt;li&gt;Concurrency feels natural and lightweight
&lt;/li&gt;
&lt;li&gt;Runtime handles scheduling automatically
&lt;/li&gt;
&lt;li&gt;Scales easily to thousands/millions of goroutines
&lt;/li&gt;
&lt;li&gt;Cleaner mental model for independent tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less explicit control over scheduling
&lt;/li&gt;
&lt;li&gt;Can accidentally create race conditions if not careful
&lt;/li&gt;
&lt;li&gt;Requires channels or sync primitives for safe communication
&lt;/li&gt;
&lt;li&gt;Debugging concurrency issues can feel more opaque
&lt;/li&gt;
&lt;li&gt;“Too easy to start tasks” can lead to uncontrolled goroutine growth&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Channels Made It Even Clearer
&lt;/h2&gt;

&lt;p&gt;Goroutines alone are powerful, but channels complete the picture. Instead of shared memory and locks, Go encourages communication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;  
&lt;span class="p"&gt;}()&lt;/span&gt;  
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is simple:&lt;br&gt;&lt;br&gt;
Don’t share memory. Communicate instead. That forces a clean mental model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who sends data?
&lt;/li&gt;
&lt;li&gt;Who receives it?
&lt;/li&gt;
&lt;li&gt;What flows through the system?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why It Clicked After Python Async
&lt;/h2&gt;

&lt;p&gt;Ironically, I don’t think goroutines would’ve made sense to me without first struggling through Python async.&lt;br&gt;&lt;br&gt;
Python taught me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concurrency is not parallelism
&lt;/li&gt;
&lt;li&gt;Blocking matters
&lt;/li&gt;
&lt;li&gt;Coordination is hard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go removed the ceremony and exposed the core idea: Concurrency is just structuring multiple flows of work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Control vs Trust
&lt;/h2&gt;

&lt;p&gt;Python async gives you control, so you decide when things pause. Go gives you trust, the runtime handles scheduling.&lt;br&gt;&lt;br&gt;
That shift is subtle but powerful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python: “I will manage concurrency carefully”
&lt;/li&gt;
&lt;li&gt;Go: “I will describe work and let the system handle it”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, trust feels risky. But it’s also what makes Go feel effortless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Learning Go didn’t just give me a new tool, it changed how I think about concurrent systems. I still use Python and appreciate async/await, but I see it more clearly: it’s structured concurrency with explicit control. And in Go, I stop thinking about pauses . I just think: Start this. Let it run. Communicate when needed. That’s what finally made concurrency click. Its been a pretty fun journey, Let me know your thoughts, Like, Share and Comment what you think.  &lt;/p&gt;

</description>
      <category>python</category>
      <category>go</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>The Bilingual Developer: Python and Go Looping &amp; Iteration</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 12 Jun 2026 18:13:42 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-looping-iteration-cgl</link>
      <guid>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-looping-iteration-cgl</guid>
      <description>&lt;p&gt;In the last article, I wrote about how programs make decisions using conditionals. We went through how a program can make a decision, choosing one path over another based on whether a condition is true or false.&lt;/p&gt;

&lt;p&gt;But what if we need to perform the same action multiple times? Let's say you have a list of about 1,000 users and want to email each of them. You wouldn't write the email-sending code 1,000 times. Instead, you would write it once and have the program repeat it for each user. This is where looping comes in.&lt;/p&gt;

&lt;p&gt;Looping allows a program to repeatedly execute a block of code until a condition is met or until all items in a collection have been processed. It's one of the most powerful concepts in programming because it helps us automate repetitive tasks and work with large amounts of data efficiently. Whether you're building a web application, analyzing data, processing files, or developing APIs, you'll find loops everywhere. Let's see how Python and Go approach this concept.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Iteration
&lt;/h2&gt;

&lt;p&gt;Iteration simply means moving through a collection of data one item at a time. For example, if you have:&lt;br&gt;&lt;br&gt;
students = ["John", "Sarah", "David"]&lt;br&gt;&lt;br&gt;
Iteration means accessing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;John
&lt;/li&gt;
&lt;li&gt;Sarah
&lt;/li&gt;
&lt;li&gt;David&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;one after another. Loops are the mechanism that makes iteration possible. We will now consider some types of loops, first the for loop.&lt;/p&gt;

&lt;p&gt;The For Loop&lt;/p&gt;

&lt;p&gt;A for loop is used when you want to repeat something a specific number of times or go through a collection of items. &lt;/p&gt;
&lt;h2&gt;
  
  
  Python's Approach: for item in sequence
&lt;/h2&gt;

&lt;p&gt;Python's for loop is designed around iteration. Instead of asking you to manage counters manually, Python allows you to directly loop through a sequence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sarah&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;David&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;students&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you read that aloud, it almost sounds like English: “For each student in students, print the student.” That's one of the reasons Python is often praised for readability. Python also provides the range() function when you want to repeat something a specific number of times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&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="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="nf"&gt;print&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0  
1  
2  
3  
4  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can note that Python focuses less on how the loop works internally and more on what you're trying to accomplish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go's Approach: The Universal for Keyword
&lt;/h2&gt;

&lt;p&gt;Instead of providing separate loop structures for different situations, Go uses a single keyword: for. This one keyword handles almost every looping scenario.&lt;br&gt;&lt;br&gt;
A traditional Go for loop looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure contains three parts: initialization; condition; post-action&lt;br&gt;&lt;br&gt;
In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;i := 0 initializes the counter
&lt;/li&gt;
&lt;li&gt;i &amp;lt; 5 determines how long the loop runs (in this case limiting to 5)
&lt;/li&gt;
&lt;li&gt;i++ updates the counter by 1 after each iteration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When iterating over collections, Go uses the range keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;students&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sarah"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"David"&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;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;student&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;students&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;student&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;Unlike Python, Go exposes both the position and the value by default.&lt;br&gt;&lt;br&gt;
This reflects Go's preference for being explicit about what's happening during execution.&lt;/p&gt;
&lt;h2&gt;
  
  
  The While Loop
&lt;/h2&gt;

&lt;p&gt;Not every situation involves iterating through a collection. Sometimes you want code to keep running as long as a condition remains true.&lt;br&gt;&lt;br&gt;
For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep asking for a password until the user enters the correct one.
&lt;/li&gt;
&lt;li&gt;Continue processing requests while the server is running.
&lt;/li&gt;
&lt;li&gt;Retry an operation until it succeeds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where while loops become useful.&lt;/p&gt;
&lt;h2&gt;
  
  
  Python's Explicit while Loop
&lt;/h2&gt;

&lt;p&gt;Python provides a dedicated keyword for this purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic is straightforward, It continues running this block while the condition remains true and each time the loop runs, the condition is checked again So once the condition becomes false, the loop stops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go's Approach: Using for as a While Loop
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Go does not have a while keyword.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Instead, Go reuses its universal for loop. To create while-loop behavior, you simply remove the initialization and post-action sections.&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;count&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;  
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;count&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;h2&gt;
  
  
  Infinite Loops
&lt;/h2&gt;

&lt;p&gt;Sometimes a loop is intended to run forever until something inside it stops execution.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Running...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="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;"Running..."&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;You'll often see these in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web servers
&lt;/li&gt;
&lt;li&gt;Background workers
&lt;/li&gt;
&lt;li&gt;Event listeners
&lt;/li&gt;
&lt;li&gt;Real-time systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Breaking and Continuing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To understand breaking and continuing, we should understand that not every loop should run to completion. Sometimes we want to stop a loop early or skip a particular iteration. This is where break and continue become useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using break
&lt;/h2&gt;

&lt;p&gt;The break statement immediately terminates the loop.&lt;br&gt;&lt;br&gt;
Python example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;number&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="k"&gt;break&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0  
1  
2  
3  
4  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The moment the value reaches 5, the loop stops completely. Go works the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;break&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, execution stops as soon as the break statement is reached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using continue
&lt;/h2&gt;

&lt;p&gt;The continue statement is slightly different. Instead of stopping the loop, it skips the current iteration and moves to the next one.&lt;br&gt;&lt;br&gt;
Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;number&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="k"&gt;continue&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0  
1  
3  
4  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that 2 is skipped. Go behaves the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;continue&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current iteration is skipped, but the loop itself continues running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python's Angle vs Go's Angle
&lt;/h2&gt;

&lt;p&gt;Looking at loops gives us another glimpse into the philosophy of both languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Python's Angle&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Python is designed to make iteration feel natural.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for item in sequence
&lt;/li&gt;
&lt;li&gt;Dedicated while keyword
&lt;/li&gt;
&lt;li&gt;Readable syntax
&lt;/li&gt;
&lt;li&gt;Focus on expressing intent clearly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Python often hides implementation details so you can focus on solving the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Go's Angle&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Go prefers consistency over having many specialized constructs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One loop keyword (for)
&lt;/li&gt;
&lt;li&gt;Multiple looping styles using the same structure
&lt;/li&gt;
&lt;li&gt;Explicit control over loop behavior
&lt;/li&gt;
&lt;li&gt;Less language complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go's mindset is:&lt;br&gt;&lt;br&gt;
Learn one loop mechanism and use it everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Looping is one of the fast ways programs get work done in programming. Without loops, applications would struggle to process lists, handle user input, analyze data, or automate repetitive tasks. Python gives you specialized, highly readable constructs for iteration. Go gives you a single, versatile tool that can adapt to different situations.Both approaches are effective.&lt;/p&gt;

&lt;p&gt;The real skill as a bilingual developer isn't memorizing syntax, but it's understanding the underlying concept. Once you understand what a loop is trying to achieve, switching between Python and Go becomes much easier. The syntax may change, but the logic remains exactly the same: repeat a task until you're done. Thanks for reading this article, hit the like and comment what you think, thanks.  &lt;/p&gt;

</description>
      <category>python</category>
      <category>go</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Rewrote Our REST API in GraphQL, Here's When It's Worth It</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Tue, 09 Jun 2026 09:55:34 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/i-rewrote-our-rest-api-in-graphql-heres-when-its-worth-it-nkf</link>
      <guid>https://dev.to/ezeanamichael/i-rewrote-our-rest-api-in-graphql-heres-when-its-worth-it-nkf</guid>
      <description>&lt;p&gt;For most of my development career, REST was my only way of building APIs. It was what I learned first, and it stayed with me. I used it in different applications, including business applications, GIS platforms, dashboards, and e-commerce systems. REST felt natural because it was structured around resources, and the HTTP protocol made everything predictable.&lt;/p&gt;

&lt;p&gt;I never really had a strong reason to explore GraphQL. It always felt like something that introduced extra level complexity and uncertainty without a clear benefit in a real production environment. That changed when I decided to rebuild part of an existing REST API using GraphQL, not as a replacement, but as an experiment to understand where it actually fits.&lt;/p&gt;

&lt;h2&gt;
  
  
  How REST Structures Systems
&lt;/h2&gt;

&lt;p&gt;REST works by exposing resources through endpoints. In an e-commerce system, this typically looks like a clear separation of concerns across entities.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GET /products/100&lt;br&gt;&lt;br&gt;
GET /products/100/reviews&lt;br&gt;&lt;br&gt;
GET /products/100/related&lt;br&gt;&lt;br&gt;
GET /sellers/20&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each endpoint returns a specific dataset, and the frontend is responsible for combining them.&lt;/p&gt;

&lt;p&gt;A simple product response might look like this:&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;100&lt;/span&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;"Wireless Headphones"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"seller_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;20&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;Then another request is required to fetch the seller:&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;20&lt;/span&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;"Tech Store"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.7&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 structure works well because it is simple, explicit, and easy to debug. REST aligns strongly with business workflows where operations are clearly defined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where REST Starts to Show Limits
&lt;/h2&gt;

&lt;p&gt;The challenge appears when frontend screens become more data-heavy. A single page in a modern application is rarely powered by a single endpoint. For a product page in an e-commerce system, the frontend may need product details, seller information, reviews, inventory, and related products.&lt;/p&gt;

&lt;p&gt;With REST, this often becomes multiple sequential or parallel requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /products/100  
GET /sellers/20  
GET /products/100/reviews  
GET /inventory/100  
GET /products/100/related
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend is forced to merge these responses into one coherent view. On fast networks, this is manageable. On slower networks or mobile devices, it introduces latency and complexity in state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  How GraphQL Changes the Model
&lt;/h2&gt;

&lt;p&gt;GraphQL shifts the responsibility from multiple endpoints to a single query system. So Instead of the server deciding what each endpoint returns, the client defines exactly what it needs.&lt;/p&gt;

&lt;p&gt;A GraphQL query for the same product page might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&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;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;seller&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="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;rating&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="n"&gt;reviews&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="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;rating&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="n"&gt;inventory&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="n"&gt;quantity&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;warehouse&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="n"&gt;relatedProducts&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="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;price&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;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;The response comes back in a single structured payload:&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;"data"&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;span class="nl"&gt;"product"&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;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;"Wireless Headphones"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"seller"&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;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;"Tech Store"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.7&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;"reviews"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
          &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
          &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Very good quality"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
          &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&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;span class="nl"&gt;"inventory"&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;span class="nl"&gt;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"warehouse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lagos Hub"&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;"relatedProducts"&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;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;"Bluetooth Speaker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
          &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&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;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="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;Instead of multiple requests, everything is resolved in one round trip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend Structure Comparison
&lt;/h2&gt;

&lt;p&gt;A REST controller typically looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/products/&amp;lt;int:id&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get_product_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/products/&amp;lt;int:id&amp;gt;/reviews&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_reviews&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get_reviews_by_product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&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;In GraphQL, the structure shifts to types and resolvers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="n"&gt;seller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Seller&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;reviews&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Review&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resolve_product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch_product_with_relations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&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;The important difference lies in how data relationships are modeled. REST separates concerns by endpoint. GraphQL models relationships directly inside the type system.&lt;/p&gt;

&lt;h2&gt;
  
  
  GIS Example Where GraphQL Becomes More Obvious
&lt;/h2&gt;

&lt;p&gt;In GIS and land management systems, data is naturally relational. A single land parcel is connected to many entities.&lt;/p&gt;

&lt;p&gt;With REST, this might require multiple endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /lands/100  
GET /owners/25  
GET /surveys/10  
GET /documents?land_id=100  
GET /transactions?land_id=100
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With GraphQL, the same structure becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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="n"&gt;land&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&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;span class="n"&gt;parcelNumber&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;owner&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="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;phone&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="n"&gt;survey&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="n"&gt;surveyor&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;date&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="n"&gt;documents&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="n"&gt;fileName&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="n"&gt;transactions&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="n"&gt;amount&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="n"&gt;date&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;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;The response mirrors the real-world relationship between entities instead of forcing the frontend to assemble it manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where GraphQL Does Not Replace REST
&lt;/h2&gt;

&lt;p&gt;GraphQL is not designed for business operations. It is not ideal for workflows that involve state changes, validations, and side effects.&lt;/p&gt;

&lt;p&gt;Actions like the following still fit REST better:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;POST /orders&lt;br&gt;&lt;br&gt;
POST /login&lt;br&gt;&lt;br&gt;
POST /payments&lt;br&gt;&lt;br&gt;
POST /upload-document&lt;br&gt;&lt;br&gt;
POST /approve-transaction&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These operations represent business intent rather than data retrieval. REST communicates that intent more clearly through HTTP semantics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protocol and Architectural Difference
&lt;/h2&gt;

&lt;p&gt;REST is built directly on HTTP methods and resource-based URLs. Each endpoint represents a specific resource or operation, and caching is naturally supported at the HTTP layer.&lt;/p&gt;

&lt;p&gt;GraphQL typically exposes a single endpoint:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;POST /graphql&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The complexity moves into the query layer. This flexibility allows precise data fetching but introduces challenges in caching, monitoring, and query optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  When GraphQL Is Worth It
&lt;/h2&gt;

&lt;p&gt;GraphQL becomes valuable in systems where data is highly connected and frontend requirements change frequently. This includes dashboards, analytics platforms, GIS systems, social applications, and mobile apps that require aggregated data from multiple sources.&lt;/p&gt;

&lt;p&gt;REST remains stronger in systems that are workflow-driven, transactional, and action-oriented.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally,
&lt;/h2&gt;

&lt;p&gt;After working with both approaches, the conclusion is not that one replaces the other. It is that they solve different categories of problems. REST is better suited for business operations and system workflows. GraphQL is better suited for flexible data retrieval in highly relational systems.In most real-world architectures, the right answer is not choosing one over the other, but understanding where each one fits and combining them intentionally. &lt;/p&gt;

&lt;p&gt;What’s your opinion? Let me know in the comments below, give a good read, like and share.&lt;/p&gt;

</description>
      <category>restapi</category>
      <category>graphql</category>
      <category>backenddevelopment</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Bilingual Developer: Python and Go Conditionals</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 05 Jun 2026 16:09:06 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-conditionals-12h5</link>
      <guid>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-conditionals-12h5</guid>
      <description>&lt;p&gt;So far, we've talked about how data is stored in memory and the different data types available in Python and Go. Storing data is only part of programming. At some point, our programs need to make decisions.&lt;/p&gt;

&lt;p&gt;When thinking about real-world applications, you can think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should a user be allowed to log in?
&lt;/li&gt;
&lt;li&gt;Is a student eligible for admission?
&lt;/li&gt;
&lt;li&gt;Has a customer completed payment?
&lt;/li&gt;
&lt;li&gt;Should an email notification be sent?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In all these situations, the program needs to decide what action to take based on certain conditions. This is where &lt;strong&gt;conditionals&lt;/strong&gt; come in. Conditionals allow a program to make decisions based on whether a condition is true or false.&lt;/p&gt;

&lt;p&gt;Although Python and Go solve the same problem, they approach conditionals in slightly different ways. In this article, we’ll explore both.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Syntax Shift: How Python and Go Define Code Blocks
&lt;/h2&gt;

&lt;p&gt;One of the first things you'll notice when writing conditionals in Python and Go is that they define code blocks differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;In Python, Indentation Matters&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Python uses a combination of colons (:) and indentation to indicate which code belongs to a condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;  
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are an adult&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The condition ends with a colon (:).
&lt;/li&gt;
&lt;li&gt;The code inside the condition is indented.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The indentation is not optional.&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 python"&gt;&lt;code&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;  
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are an adult&lt;/span&gt;&lt;span class="sh"&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 produces an error because Python relies on indentation to understand the structure of your program. Python's philosophy here is simple:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Code should be readable and visually organized.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By forcing indentation, Python ensures that developers write code in a consistent format.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;In Go, Curly Braces Define Structure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Go takes a different route. Instead of indentation, it uses curly braces {} to define blocks of 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="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;  
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;18&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;"You are an adult"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The braces tell Go exactly where the conditional block starts and ends. Even if you change the spacing or indentation, Go still understands the structure because the braces define it. One important thing to note is that Go does not require parentheses around conditions.&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;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;18&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;"Adult"&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;Not:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adult"&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;While the second style is common in some languages, Go intentionally keeps the syntax cleaner.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;If/Else Chains&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A single condition is useful, but real applications often need multiple possible outcomes.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;A score above 70 is an A.
&lt;/li&gt;
&lt;li&gt;A score above 60 is a B.
&lt;/li&gt;
&lt;li&gt;A score above 50 is a C.
&lt;/li&gt;
&lt;li&gt;Anything lower is a fail.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where if/else chains become useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Python's elif&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Python introduces the elif keyword, which stands for "else if."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;  
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Grade A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Grade B&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Grade C&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Fail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The program checks each condition from top to bottom. As soon as one condition evaluates to True, Python executes that block and skips the rest. This keeps the code concise and easy to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Go's else if&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go achieves the same thing using else if.&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;score&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;70&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;"Grade A"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;60&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;"Grade B"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;50&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;"Grade C"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fail"&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;Functionally, this behaves exactly like Python's elif. The main difference is syntax. Python creates a special keyword (elif). Go combines two existing keywords (else if).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Quick Comparison&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;if&lt;/td&gt;
&lt;td&gt;if&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;elif&lt;/td&gt;
&lt;td&gt;else if&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;else&lt;/td&gt;
&lt;td&gt;else&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uses indentation&lt;/td&gt;
&lt;td&gt;Uses braces&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Pattern Matching and Multi-Way Decisions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes an application needs to compare a value against many possible options. Imagine you're building a system that handles user roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin
&lt;/li&gt;
&lt;li&gt;Staff
&lt;/li&gt;
&lt;li&gt;Student
&lt;/li&gt;
&lt;li&gt;Guest&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using multiple if statements can become messy. Both Python and Go provide a cleaner solution, but they do it differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Python's match/case&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Starting from Python 3.10, Python introduced match/case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Full access&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Staff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Limited access&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Student&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Student access&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Guest access&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of match as saying:&lt;/p&gt;

&lt;p&gt;"Compare this value against several patterns and execute the matching block."&lt;/p&gt;

&lt;p&gt;The underscore (_) acts as a default case. One reason match/case is powerful is that it can do more than simple value comparisons.&lt;/p&gt;

&lt;p&gt;It can match:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Values
&lt;/li&gt;
&lt;li&gt;Lists
&lt;/li&gt;
&lt;li&gt;Tuples
&lt;/li&gt;
&lt;li&gt;Object structures
&lt;/li&gt;
&lt;li&gt;Complex patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it much more powerful than traditional switch statements found in many languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Go's switch Statement&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go uses switch.&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;role&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Admin"&lt;/span&gt;  
&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Admin"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Full access"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Staff"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Limited access"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Student"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Student access"&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;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;"Guest access"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, this looks similar to Python's match/case. However, Go's switch statement has a few interesting capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Switch Without an Expression&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One unique feature of Go is that a switch can be used without directly switching on a variable.&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;score&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt;  
&lt;span class="k"&gt;switch&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;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Grade A"&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;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Grade B"&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;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;"Fail"&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 behaves almost like an organized replacement for a long if/else if chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Multiple Values in a Case&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go also allows multiple matching values.&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;day&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Saturday"&lt;/span&gt;  
&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Saturday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sunday"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Weekend"&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;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;"Weekday"&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 can make decision logic much cleaner.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: Python's Angle vs Go's Angle&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Python's Angle&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Python focuses on readability and expressiveness.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Indentation clearly shows structure.
&lt;/li&gt;
&lt;li&gt;elif makes multi-condition chains easy to read.
&lt;/li&gt;
&lt;li&gt;match/case supports powerful pattern matching.
&lt;/li&gt;
&lt;li&gt;The language tries to make decision logic feel natural and close to plain English.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Go's Angle&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Go focuses on simplicity and predictability.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Curly braces explicitly define blocks.
&lt;/li&gt;
&lt;li&gt;else if keeps the language small by reusing existing keywords.
&lt;/li&gt;
&lt;li&gt;The switch is versatile enough to replace many if/else chains.
&lt;/li&gt;
&lt;li&gt;The language avoids adding too many specialized features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading. Hope you learned something new. Read, like and comment, thanks.&lt;/p&gt;

</description>
      <category>python</category>
      <category>go</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>7 REST API Mistakes I Made as a Junior Developer</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Tue, 02 Jun 2026 16:27:15 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/7-rest-api-mistakes-i-made-as-a-junior-developer-3b4i</link>
      <guid>https://dev.to/ezeanamichael/7-rest-api-mistakes-i-made-as-a-junior-developer-3b4i</guid>
      <description>&lt;p&gt;REST APIs are one way applications exchange information, especially between the client and server sides of modern systems. APIs are created on the server and consumed by web, mobile, or desktop clients.&lt;/p&gt;

&lt;p&gt;When I started my career as a junior developer, I built several APIs that worked, but I learned lessons through experience. My APIs were not always designed with scalability, maintainability, or even best practices in mind. As I gained more experience, I discovered some mistakes that I repeatedly made and learned how to correct them.&lt;/p&gt;

&lt;p&gt;Here are seven REST API mistakes I made as a junior developer and the lessons I learned from them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Not Versioning My APIs Early&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the biggest mistakes I made was launching APIs without versioning them from the start. At first, this seemed fine because there was only one client consuming the API. However, as the requirements changed, introducing breaking changes became difficult because existing clients depended on the old structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned is this:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Always version your APIs from day one, even if you don't think you'll need multiple versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;/api/v1/users
&lt;/li&gt;
&lt;li&gt;/api/v1/orders
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Versioning helps to give you the flexibility to evolve your API without breaking existing consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Overloading GET Endpoints&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I used to create GET endpoints that returned every piece of information about a resource, including large nested objects and related records. This often resulted in slow responses and unnecessary data transfer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned is this:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Not every endpoint needs to return full details. It's perfectly acceptable to have(For Example):&lt;/p&gt;

&lt;p&gt;GET /users&lt;/p&gt;

&lt;p&gt;To return a summarized view:&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;"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;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&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;And then use:&lt;/p&gt;

&lt;p&gt;GET /users/1&lt;/p&gt;

&lt;p&gt;To return complete information about the user. This approach improves performance and reduces payload sizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Exposing My Database Structure Directly&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Early in my career, I mapped database tables directly to API responses. As a result, clients became tightly coupled to the database design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad Example:&lt;/strong&gt;&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;"tbl_user_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;"tbl_user_fname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&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;&lt;strong&gt;What I Learned is this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An API should represent business resources, not database tables. A cleaner response would be:&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;"first_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;"John"&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 gives us the freedom to modify our database without affecting API consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;4. Not Implementing Pagination Early&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One mistake I made was returning entire datasets from the API. This worked fine during development when there were only a few records, but it quickly became a performance issue as the application grew.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned is this:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Large datasets should be paginated from the beginning. Instead of:&lt;/p&gt;

&lt;p&gt;GET /users&lt;/p&gt;

&lt;p&gt;Returning thousands of records, use pagination:&lt;/p&gt;

&lt;p&gt;GET /users?page=1&amp;amp;limit=20&lt;/p&gt;

&lt;p&gt;Pagination improves performance, reduces bandwidth usage, and provides a better experience for API consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. Not Thinking About Authentication and Authorization Early&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As a junior developer, I focused heavily on making endpoints work and sometimes overlooked who should be allowed to access them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned is this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Authentication and authorization should be part of the API design process from the start.&lt;/p&gt;

&lt;p&gt;Ask questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who can access this endpoint?
&lt;/li&gt;
&lt;li&gt;Should this action require login?
&lt;/li&gt;
&lt;li&gt;Are there admin-only operations?
&lt;/li&gt;
&lt;li&gt;What happens if an unauthorized user makes a request?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing proper access control early helps prevent security issues during development and future refactoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;6. Not Standardizing Error Responses&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In some projects, every endpoint returned errors differently. One endpoint might return a message, another might return a list of errors, while another might return a completely different structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned is this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Error responses should follow a consistent format throughout the API.&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;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USER_NOT_FOUND"&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;A standardized error structure makes debugging easier and allows frontend developers to handle errors consistently across the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;7. Skipping Documentation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As a junior developer, I often assumed that my API endpoints were self-explanatory. They weren't. Even I sometimes forgot how certain endpoints worked after a few weeks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned is this:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Good documentation saves time for both API consumers(Frontend developers and others) and future maintainers.&lt;/p&gt;

&lt;p&gt;Document:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Endpoint URLs
&lt;/li&gt;
&lt;li&gt;Request methods
&lt;/li&gt;
&lt;li&gt;Request parameters
&lt;/li&gt;
&lt;li&gt;Authentication requirements
&lt;/li&gt;
&lt;li&gt;Response examples
&lt;/li&gt;
&lt;li&gt;Error responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clear documentation reduces misunderstandings and speeds up integration efforts.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Building APIs that simply work is relatively easy. Building APIs that are maintainable, scalable, and pleasant for other developers to consume requires more thought and experience.&lt;/p&gt;

&lt;p&gt;Looking back, these mistakes taught me valuable lessons about API design. Today, whenever I create a new REST API, I focus on versioning early, keeping responses consistent, using proper HTTP methods, avoiding database leakage, and designing endpoints with long-term maintainability in mind.&lt;/p&gt;

&lt;p&gt;The best API designs are often the simplest ones: predictable, well-documented, and easy for other developers to understand. Thanks for going through my article. Please leave a like and comment. Thanks.&lt;/p&gt;

</description>
      <category>restapi</category>
      <category>backenddevelopment</category>
      <category>webdev</category>
      <category>developer</category>
    </item>
    <item>
      <title>The Bilingual Developer: Python and Go Primitive Data Types</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 29 May 2026 15:50:56 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-primitive-data-types-4c5f</link>
      <guid>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-primitive-data-types-4c5f</guid>
      <description>&lt;p&gt;As discussed in the previous article on the variables about the need of programming languages to store information. This article will be about how the different data is stored. Let’s slow it down a bit and really think about it. If storage is where data lives… then data types are basically &lt;em&gt;how that data is shaped inside memory.&lt;/em&gt; And depending on the language you’re using, that “shape” changes a lot. Primitive data types are the most basic building blocks used to represent values inside a program.&lt;/p&gt;

&lt;p&gt;When learning both Python and Go, understanding their primitive data types is one of the fastest ways to understand the design philosophy behind each language.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Understanding Primitive Data Types&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Primitive data types are the simplest forms of data a programming language can handle directly. They represent single values such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text
&lt;/li&gt;
&lt;li&gt;Numbers
&lt;/li&gt;
&lt;li&gt;Boolean values (true or false)
&lt;/li&gt;
&lt;li&gt;Fixed constant values&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Text and Characters&lt;/strong&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Strings in Python&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In Python, text is represented using the &lt;code&gt;str&lt;/code&gt; data type. A string, simply put, is a sequence of characters enclosed in quotation marks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Michael&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello World&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python treats strings as Unicode by default, meaning they can store characters from different languages and symbols.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;😊&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
&lt;span class="n"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of Python’s strengths is how simple string manipulation feels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;first_word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Go&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
&lt;span class="n"&gt;last_word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;full_word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_word&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;last_word&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Go Python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python does not have a separate character (&lt;code&gt;char&lt;/code&gt;) data type. A single character is simply considered a string of length one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;class 'str'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This design keeps the language simpler because developers only need to think about one text type instead of multiple character-based types.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Strings and Runes in Go&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go also uses strings for textual data.&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Michael"&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But Go handles characters differently from Python.&lt;/p&gt;

&lt;p&gt;In Go:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A string represents a sequence of bytes.
&lt;/li&gt;
&lt;li&gt;A rune represents a single Unicode character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A rune is actually an alias for &lt;code&gt;int32&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;var letter rune = 'A'&lt;/p&gt;

&lt;p&gt;Notice something important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strings use double quotes &lt;code&gt;" "&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Runes use single quotes &lt;code&gt;' '&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This distinction is very important in Go.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;character&lt;/span&gt; &lt;span class="kt"&gt;rune&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'G'&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character&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;Output:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The output is numeric because Go stores runes internally using Unicode code points.&lt;/p&gt;

&lt;p&gt;To print the actual character:&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%cn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;Go’s approach gives developers more control over memory and encoding behavior, especially for systems programming and high-performance applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Numbers&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Numbers are another core primitive data type.&lt;/p&gt;

&lt;p&gt;Both Python and Go support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integers
&lt;/li&gt;
&lt;li&gt;Floating-point numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Integers and Floats in Python&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Python makes numeric programming simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;  
&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;19.99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python automatically determines the type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;class 'int'&amp;gt;  
&amp;lt;class 'float'&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important feature of Python is that integers can grow very large automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;big_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;999999999999999999999999999999&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python dynamically allocates memory for large integers behind the scenes.&lt;/p&gt;

&lt;p&gt;This flexibility is convenient because developers rarely worry about integer overflow or memory size during basic programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Integers and Floats in Go&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go is stricter and more explicit.&lt;/p&gt;

&lt;p&gt;var age int = 25&lt;br&gt;&lt;br&gt;
var price float64 = 19.99&lt;/p&gt;

&lt;p&gt;Go supports multiple integer sizes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;int8&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;int16&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;int32&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int64&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And floating-point types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;float32&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;float64&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;smallNumber&lt;/span&gt; &lt;span class="kt"&gt;int8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;  
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;largeNumber&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;9000000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This explicit sizing is important because each type uses a specific amount of memory.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;int8&lt;/td&gt;
&lt;td&gt;8 bits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int16&lt;/td&gt;
&lt;td&gt;16 bits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int32&lt;/td&gt;
&lt;td&gt;32 bits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int64&lt;/td&gt;
&lt;td&gt;64 bits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Go forces developers to think more carefully about memory usage and performance.&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 go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;  
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;

&lt;span class="c"&gt;// This causes an error  &lt;/span&gt;
&lt;span class="c"&gt;// fmt.Println(x + y)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go does not automatically mix different integer sizes. Developers must explicitly convert types.&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;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This strictness reduces accidental bugs and improves predictability in large systems.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Booleans&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Booleans represent logical truth values.&lt;/p&gt;

&lt;p&gt;They are heavily used in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conditions
&lt;/li&gt;
&lt;li&gt;Comparisons
&lt;/li&gt;
&lt;li&gt;Decision-making statements&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Booleans in Python&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Python uses:&lt;/p&gt;

&lt;p&gt;True and False&lt;/p&gt;

&lt;p&gt;Notice the capitalization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;is_logged_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;  
&lt;span class="n"&gt;is_admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;  
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;Python’s boolean system is highly flexible because many values can behave as truthy or falsy.&lt;/p&gt;

&lt;p&gt;Examples of falsy values:&lt;/p&gt;

&lt;p&gt;0&lt;br&gt;&lt;br&gt;
None&lt;br&gt;&lt;br&gt;
""&lt;br&gt;&lt;br&gt;
[]&lt;br&gt;&lt;br&gt;
False&lt;/p&gt;

&lt;p&gt;Everything else is generally considered truthy.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Booleans in Go&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go also supports boolean values, but with stricter rules(as usual).&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;isLoggedIn&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;  
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;isAdmin&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the lowercase keywords:&lt;/p&gt;

&lt;p&gt;true and false&lt;/p&gt;

&lt;p&gt;Go does not allow non-boolean values in conditional statements.&lt;/p&gt;

&lt;p&gt;This is invalid:&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;number&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&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;Python allows similar truthy checks, but Go requires an actual boolean expression.&lt;/p&gt;

&lt;p&gt;Correct Go example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&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 design improves clarity and reduces ambiguity.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Constants&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Constants are values that should never change during program execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Constants in Python&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Python does not have a true constant keyword. Instead, developers follow a naming convention using uppercase variable names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14159&lt;/span&gt;  
&lt;span class="n"&gt;MAX_USERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, Python does not enforce immutability.&lt;/p&gt;

&lt;p&gt;PI = 10&lt;/p&gt;

&lt;p&gt;This still works. The uppercase naming style simply communicates intent to other developers. Python relies heavily on developer discipline and readability conventions.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Constants in Go&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go provides an actual &lt;code&gt;const&lt;/code&gt; keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3.14159&lt;/span&gt;  
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MaxUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once declared, constants cannot be modified.&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;const&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;

&lt;span class="c"&gt;// Error  &lt;/span&gt;
&lt;span class="c"&gt;// Age = 30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enforcement makes programs safer and more predictable. Go constants can also exist without explicitly specifying a type.&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;const&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"GoLang"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler determines the appropriate type automatically.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;In Python, primitive types are designed to feel natural and easy to use. Developers can move quickly without worrying much about memory sizes or strict typing rules.&lt;/p&gt;

&lt;p&gt;In Go, primitive types are more structured and explicit. Developers are expected to think carefully about memory, type safety, and predictability.&lt;/p&gt;

&lt;p&gt;Comment , Share and Like, thanks for reading.&lt;/p&gt;

</description>
      <category>python</category>
      <category>go</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>The N+1 Query That Killed Our Database, And How I Fixed It</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Mon, 25 May 2026 17:39:38 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/the-n1-query-that-killed-our-database-and-how-i-fixed-it-2al5</link>
      <guid>https://dev.to/ezeanamichael/the-n1-query-that-killed-our-database-and-how-i-fixed-it-2al5</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Everything Worked…But Not Well&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;APIs are affected by the way data is retrieved from the database, and that's something that affected a recent teammate and me during development. In our regular development process, during review and maintenance, the APIs worked, responses came back well, no visible errors. But during this process, we noticed that things started to slow down. Endpoints that used to respond fast suddenly began taking longer, CPU usage on the database increased, and retrieval speed became terrible under load.&lt;/p&gt;

&lt;p&gt;At first, we thought:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maybe the server wasn't powerful enough
&lt;/li&gt;
&lt;li&gt;Maybe network latency was the issue
&lt;/li&gt;
&lt;li&gt;Maybe too many requests were hitting the API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the real issue was hiding inside our database queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Actually Is The N+1 Query Problem?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The N+1 query problem is one of the most common performance issues in backend development, especially when working with relational databases and ORMs(as I, a fan of Django, do). I’m gonna explain this more in SQL terms using retrieval speed and database load.&lt;/p&gt;

&lt;p&gt;The problem happens when your application performs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 query to retrieve parent records
&lt;/li&gt;
&lt;li&gt;Then N extra queries to retrieve related child records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So instead of making one optimized query, the application keeps asking the database more questions repeatedly. This increases the query count, read time, database load, and the API response time. 1 issue, several systems affected.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Simple Example&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's say we have 2 tables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users
&lt;/li&gt;
&lt;li&gt;Orders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We first retrieve all users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM users;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine there are 100 users. Then, for every user retrieved, another query runs to fetch their orders.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM orders WHERE user_id = 1;  
SELECT * FROM orders WHERE user_id = 2;  
SELECT * FROM orders WHERE user_id = 3;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it keeps going. So instead of 1 query, you now have 101 queries. That extra load destroys retrieval speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why This Problem Is Dangerous&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The dangerous part is that during development, you might not even notice it. If your database only has just about 5 users and 10 orders, Everything still feels fast.&lt;/p&gt;

&lt;p&gt;But once production data grows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hundreds of users
&lt;/li&gt;
&lt;li&gt;Thousands of records
&lt;/li&gt;
&lt;li&gt;More API requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The database starts struggling badly. This is why some APIs feel fast during testing but start to  slow down after deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Mistake We Made&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The issue wasnt obvious at first because the code itself looked completely normal. We had an endpoint that needed to return users alongside their related orders.&lt;/p&gt;

&lt;p&gt;Something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User information
&lt;/li&gt;
&lt;li&gt;Their recent orders
&lt;/li&gt;
&lt;li&gt;Order counts
&lt;/li&gt;
&lt;li&gt;Related details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The endpoint worked perfectly during development. But internally, Django was fetching related records separately for every user being serialized. Which meant the API kept hitting the database repeatedly behind the scenes.&lt;/p&gt;

&lt;p&gt;The code looked clean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users = User.objects.all()

serializer = UserSerializer(users, many=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But in the serializer, related order data was being accessed for every single user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserSerializer(serializers.ModelSerializer):

    orders = OrderSerializer(many=True)

    class Meta:

        model = User

        fields = ['id', 'name', 'orders']

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

&lt;/div&gt;



&lt;p&gt;This is where the real problem started. When Django tried to serialize the response, it kept querying orders separately per user. So if there were 500 users, the system would do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 query to retrieve users
&lt;/li&gt;
&lt;li&gt;Hundreds of additional queries to retrieve orders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the N+1 query problem. The scary part is that nothing looked wrong from the surface. The endpoint returned the correct data and no errors, just slow performance. And as traffic increased, the database load became worse. It was slow because the application kept repeatedly asking for related data instead of retrieving it efficiently.&lt;/p&gt;

&lt;p&gt;The fix was adding query optimization directly to the queryset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users = User.objects.prefetch_related('orders')

serializer = UserSerializer(users, many=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That single optimization drastically reduced the number of database hits. Instead of querying orders repeatedly for every user, Django retrieved them efficiently in bulk. Same endpoint and response, much better performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding &lt;code&gt;select_related()&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One major fix for this problem in Django is:&lt;/p&gt;

&lt;p&gt;select_related()&lt;/p&gt;

&lt;p&gt;&lt;code&gt;select_related()&lt;/code&gt; is used for relationships like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ForeignKey
&lt;/li&gt;
&lt;li&gt;OneToOneField&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it basically does is perform a SQL JOIN and retrieve related data in a single query. Instead of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users = User.objects.all()

for user in users:  
    print(user.profile.phone)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which may generate multiple queries…&lt;/p&gt;

&lt;p&gt;You do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;users = User.objects.select_related('profile')  
for user in users:  
    print(user.profile.phone)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Django joins the tables together and retrieves everything at once.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;1 query for users
&lt;/li&gt;
&lt;li&gt;Multiple queries for profiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You now get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 optimized query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Much faster and cleaner.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding &lt;code&gt;prefetch_related()&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Another optimization is:&lt;/p&gt;

&lt;p&gt;prefetch_related()&lt;/p&gt;

&lt;p&gt;This is used mostly for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ManyToMany relationships
&lt;/li&gt;
&lt;li&gt;Reverse ForeignKey relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike &lt;code&gt;select_related()&lt;/code&gt;, this does not use SQL JOINs directly. Instead, Django performs separate queries but combines the results efficiently in memory.&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 plaintext"&gt;&lt;code&gt;users = User.objects.prefetch_related('orders')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django may run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM users;  
SELECT * FROM orders WHERE user_id IN (1,2,3,4...);
&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 plaintext"&gt;&lt;code&gt;SELECT * FROM orders WHERE user_id = 1;  
SELECT * FROM orders WHERE user_id = 2;  
SELECT * FROM orders WHERE user_id = 3;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is far more efficient. So rather than hundreds of queries, you may only have two.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Difference Between &lt;code&gt;select_related()&lt;/code&gt; And &lt;code&gt;prefetch_related()&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;select_related()&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses SQL JOINs
&lt;/li&gt;
&lt;li&gt;Best for ForeignKey and OneToOne relationships
&lt;/li&gt;
&lt;li&gt;Retrieves related data in a single query&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;prefetch_related()&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses multiple optimized queries
&lt;/li&gt;
&lt;li&gt;Combines data in Python memory
&lt;/li&gt;
&lt;li&gt;Best for ManyToMany and reverse relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both solve the same problem differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Result&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After fixing the queries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Response times dropped massively
&lt;/li&gt;
&lt;li&gt;Database load reduced
&lt;/li&gt;
&lt;li&gt;API became stable again
&lt;/li&gt;
&lt;li&gt;Retrieval speed improved significantly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The funny thing is that we didnt upgrade the server. We didnt increase RAM. We didnt change infrastructure. We simply reduced unnecessary queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What This Experience Taught Me&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One thing this experience taught me is that backend performance is not always about server power. Sometimes your database is suffering simply because of how you are querying it. A badly written retrieval pattern can quietly destroy performance even when your infrastructure is good. Now whenever I build endpoints, I dont just ask “Does this work?” I also ask “How many queries is this generating behind the scenes?” Because sometimes the biggest backend problem is not the logic. Its the retrieval pattern hiding underneath it. Let me know what you think, thanks for reading, like, share, comment and follow for more. &lt;/p&gt;

</description>
      <category>database</category>
      <category>python</category>
      <category>django</category>
      <category>sql</category>
    </item>
    <item>
      <title>How I Cut API Response Time from 2s to &lt;100ms with Redis Caching</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 22 May 2026 15:09:42 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/how-i-cut-api-response-time-from-2s-to-100ms-with-redis-caching-4h6a</link>
      <guid>https://dev.to/ezeanamichael/how-i-cut-api-response-time-from-2s-to-100ms-with-redis-caching-4h6a</guid>
      <description>&lt;p&gt;Early in my software development years, I had the opportunity to work with a company where I learned backend development. I worked on a system where I was responsible for building the APIs without senior guidance, just documentation, experimentation, and a lot of self-learning.&lt;br&gt;&lt;br&gt;
When learning to design DB models and RESTful APIs. That was it for me, connect everything and let it out via the get request, let it in via the post request, patch things up with the patch request, and delete via the delete request. &lt;/p&gt;

&lt;p&gt;Basic crud operations, and I was fine with that, back then. Eventually, I decided to explore the site myself, and damn, it was slow.&lt;br&gt;&lt;br&gt;
Every interaction came with a noticeable delay. So I stopped assuming things were fine and tested the APIs properly. Using Postman, I measured response times. Most endpoints were taking over 5 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Every request was hitting the database directly, even when requesting the same data repeatedly.&lt;br&gt;&lt;br&gt;
The system wasn’t slow because the database was bad.&lt;br&gt;&lt;br&gt;
 It was slow because it was doing the same work over and over again.&lt;/p&gt;

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

&lt;p&gt;I did some research, investigations, and found something powerful. Caching, and utilizing redis for it. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Caching?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Caching stores frequently accessed data in memory (Redis uses RAM), allowing much faster retrieval compared to querying a database repeatedly. It reduces database load, instead of hitting the database every time it hits the cache instead and returns the result. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Types of Caching (and Why Redis Fits Here)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Not all caching works the same way. In my case, I implemented &lt;strong&gt;application-level caching with Redis&lt;/strong&gt;, but it helps to understand where it sits in the bigger picture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Application-Level Caching&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is what I used. The application stores frequently accessed data in a fast in-memory store like Redis.&lt;/p&gt;

&lt;p&gt;Instead of always asking the database:&lt;/p&gt;

&lt;p&gt;API → Database → Response&lt;/p&gt;

&lt;p&gt;We first check:&lt;/p&gt;

&lt;p&gt;API → Redis → Database (only if needed)&lt;/p&gt;

&lt;p&gt;This is the most common approach in backend systems because it gives full control over what gets cached and when it gets updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Database Caching&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Some databases internally cache query results or use external layers to store repeated query outputs.&lt;/p&gt;

&lt;p&gt;This reduces repeated expensive queries, but it is less flexible compared to Redis-based caching where you control the logic directly inside your API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Distributed Caching&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is when caching is shared across multiple servers using systems like Redis Cluster or Memcached.&lt;/p&gt;

&lt;p&gt;It becomes important when your application is no longer running on a single server, but across multiple services or microservices.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Therefore,&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before:&lt;br&gt;&lt;br&gt;
Client → API → DB (every request)&lt;/p&gt;

&lt;p&gt;After:&lt;br&gt;&lt;br&gt;
Client → API → Redis → DB (only on cache miss)&lt;/p&gt;

&lt;p&gt;Instead of querying the database every time, the API now checks Redis first. If the data exists, it returns immediately. If not, it fetches from the database, stores the result in Redis, and returns it.&lt;/p&gt;

&lt;p&gt;Here was my initial API response time without caching, &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5op2j9888e3i4dypjgop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5op2j9888e3i4dypjgop.png" alt="Postman image showing response time of over 5 seconds" width="795" height="25"&gt;&lt;/a&gt;&lt;br&gt;
Here was my API response time afterwards.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpyb4v6t1pfdk00uwps1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpyb4v6t1pfdk00uwps1.png" alt="Postman image showing response time of less that 200ms" width="783" height="23"&gt;&lt;/a&gt; &lt;br&gt;
I implemented 2 main strategies.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Key-value Caching.
&lt;/li&gt;
&lt;li&gt;Cache invalidation via Write.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my API I implemented key value caching for every get request i.e (get /books/ and get /books/:id)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Eliminating First-Request Slowness (Cache Warm-Up)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One downside of caching is the initial delay when the cache is empty.&lt;br&gt;&lt;br&gt;
How did I solve that? a script. &lt;/p&gt;

&lt;p&gt;I added a cache warm-up script that runs on deployment and preloads frequently accessed data into Redis. That way, the system starts “warm,” and users don’t experience the initial latency.&lt;/p&gt;

&lt;p&gt;At that point, the only time the system feels slow is immediately after cache invalidation.&lt;/p&gt;

&lt;p&gt;But having a cache isn't all good if not invalidated well, because write data comes in too, through post , patch, put. So a cache invalidation strategy was needed. &lt;/p&gt;

&lt;p&gt;I chose cache invalidation via Write for 2 reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Data will be refreshed once a put, patch, post or delete request comes in, and
&lt;/li&gt;
&lt;li&gt;Data is not often changed regularly, the data stays for a while because of the type of application we’re dealing with so giving it a time to live and time to die feels too much. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Trade-offs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Every system has tradeoffs as there is no perfect system. The following were the tradeoffs of my decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First request after invalidation is slower
&lt;/li&gt;
&lt;li&gt;Cache keys must be managed carefully
&lt;/li&gt;
&lt;li&gt;Slight increase in system complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the system is now significantly faster and more efficient.&lt;/p&gt;

&lt;p&gt;PS: &lt;em&gt;There are several optimization techniques in backend development, this article is just about caching.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Thanks for reading, what do you think about the approach? Read, like and comment. &lt;/p&gt;

</description>
      <category>redis</category>
      <category>backend</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Bilingual Developer: Python and Go Variables</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 22 May 2026 14:59:35 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-variables-57mm</link>
      <guid>https://dev.to/ezeanamichael/the-bilingual-developer-python-and-go-variables-57mm</guid>
      <description>&lt;p&gt;At the heart of programming is a simple idea:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input -&amp;gt; Processing -&amp;gt; Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But between input and processing lies something more important, &lt;strong&gt;storage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before a computer can do anything useful with data, it must first store it somewhere. That “somewhere” is memory. And in programming, the way we interact with memory starts with one core concept:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Programming is just a way of communicating with a computer, telling it what to store, how to transform it, and what to return.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how two very different languages, &lt;strong&gt;Python and Go&lt;/strong&gt;, handle the same idea: variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Variables: The First Mental Model&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A variable is simply a named storage location in memory.&lt;/p&gt;

&lt;p&gt;For example (What it does is):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“store the number 10”
&lt;/li&gt;
&lt;li&gt;“label it as x”
&lt;/li&gt;
&lt;li&gt;“retrieve it later when needed”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple concept,  but different languages implement it very differently.&lt;/p&gt;

&lt;p&gt;And that’s where Python and Go start to diverge.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Python vs Go: Two Different Philosophies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Python and Go both allow you to store data in variables, but they were designed with different priorities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python: flexibility and speed of writing code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go: structure, safety, and predictability&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This difference shows up immediately in how variables are declared.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Dynamic vs Static Typing&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Python (Dynamic Typing)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In Python, you don’t explicitly declare the type of a variable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x=10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjirvpxdopnyhya4y1j73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjirvpxdopnyhya4y1j73.png" alt="Python variable image" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python automatically figures out the datatype at runtime.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;dynamic typing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It gives you flexibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can reuse variables freely
&lt;/li&gt;
&lt;li&gt;You don’t need to define types upfront
&lt;/li&gt;
&lt;li&gt;It speeds up development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the trade-off is that errors may only show up when the program runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Go (Static Typing)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In Go, you must define the type explicitly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;var x int = 10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hg8qhtfezxxv61nsyku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hg8qhtfezxxv61nsyku.png" alt="Go variable Image" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once declared, the type cannot change.&lt;/p&gt;

&lt;p&gt;So this is invalid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x = "hello" // error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is called &lt;strong&gt;static typing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It forces structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Types are known before execution
&lt;/li&gt;
&lt;li&gt;Errors are caught early (at compile time)
&lt;/li&gt;
&lt;li&gt;Code is more predictable in large systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Two Ways of Declaring Variables&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Python keeps it simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x = 10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it. One way, one rule.&lt;/p&gt;

&lt;p&gt;Go gives you two main approaches:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Explicit Declaration&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;var x int = 10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;### &lt;strong&gt;Short Declaration (Walrus-style feel)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x := 10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;:=&lt;/code&gt; operator tells Go:&lt;/p&gt;

&lt;p&gt;“Infer the type automatically, but still lock it in permanently.”&lt;/p&gt;

&lt;p&gt;So Go gives you convenience — but never sacrifices structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Concept of “Nothing”&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Another major difference is how both languages handle empty or uninitialized values.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Python: &lt;code&gt;None&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In Python, “no value” is represented explicitly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x = None&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;p&gt;“This variable exists, but it currently holds nothing.”&lt;/p&gt;

&lt;p&gt;It is very explicit and readable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Go: Zero Values&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Go does something different.&lt;/p&gt;

&lt;p&gt;If you declare a variable but don’t assign a value, Go automatically gives it a default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;var x int
&lt;/li&gt;
&lt;li&gt;fmt.Println(x) // 0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So instead of &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;None&lt;/code&gt;, Go uses &lt;strong&gt;zero values&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;int → 0
&lt;/li&gt;
&lt;li&gt;string → ""
&lt;/li&gt;
&lt;li&gt;bool → false&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design avoids uninitialized variables entirely.&lt;/p&gt;

&lt;p&gt;While python thinks: “Let me give you freedom and decide later.” Go thinks: “Let me force clarity so you don’t make mistakes later.”&lt;/p&gt;

&lt;p&gt;Even something as simple as variables reveals deep design philosophies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python prioritizes &lt;strong&gt;developer speed and flexibility&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Go prioritizes &lt;strong&gt;safety and predictability&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are correct, just optimized for different worlds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python → scripting, AI, automation, rapid development
&lt;/li&gt;
&lt;li&gt;Go → backend systems, scalability, performance-critical services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading, what do you think about this? Read, like and comment.&lt;/p&gt;

</description>
      <category>python</category>
      <category>go</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Bilingual Developer: Learning Python &amp; Go Side-by-Side</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Fri, 15 May 2026 16:50:43 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/the-bilingual-developer-learning-python-go-side-by-side-3nan</link>
      <guid>https://dev.to/ezeanamichael/the-bilingual-developer-learning-python-go-side-by-side-3nan</guid>
      <description>&lt;p&gt;There are several programming languages and specialized fields today. Navigating the mountain of guides out there can be tricky; some lead you straight into "tutorial hell," while others actually help you gain a solid footing. Python and Go are two of the most popular choices in modern development, different in their own ways, each have their strengths.&lt;/p&gt;

&lt;p&gt;I, you, and many others have gone through a tutorial to learn a language one at a time, so I thought of trying something different: &lt;strong&gt;Dual-Language Learning&lt;/strong&gt;. The advantage here is that it gives you two sides of a concept, forcing you to actually understand the underlying mechanisms rather than just memorizing syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Python and Go?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt; is a &lt;strong&gt;dynamically typed&lt;/strong&gt; language, which means you can write code, iterate, and test ideas without getting held down in some boilerplate or strict type declarations. It is used for &lt;strong&gt;LLM engineering, machine learning, and rapid backend development.&lt;/strong&gt; Its real power isn't in raw execution speed (it can be slow compared to others), but developer writing speed gives it an edge; it's simpler to write than some other languages. Python serves as the ultimate "glue" language; you write clean, readable code, while the heavy computational lifting is delegated to blazing-fast C++ and Rust kernels under the hood. With industry-standard libraries like PyTorch, Hugging Face, and FastAPI, Python provides the fastest possible path from a raw AI idea to a deployed prototype.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt; (or Golang), developed by Google, is a &lt;strong&gt;statically typed&lt;/strong&gt; language, and the one word I'll use to describe it is &lt;em&gt;speed&lt;/em&gt;. It is the industry standard for &lt;strong&gt;backend infrastructure, cloud-native tooling (like Docker and Kubernetes), and high-performance microservices&lt;/strong&gt;, making it a powerhouse for things like high-throughput fintech platforms. While Python historically utilized a Global Interpreter Lock (GIL) that prevented it from running operations concurrently at maximum efficiency, &lt;strong&gt;Go handles massive concurrency natively&lt;/strong&gt;. Through "goroutines," it is blazingly fast at computing simultaneous tasks, allowing it to scale effortlessly across multiple cores.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The 2026 Landscape&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.14:&lt;/strong&gt; This release officially supports &lt;strong&gt;free-threaded Python&lt;/strong&gt; (allowing you to disable the GIL for true multithreading) and introduces an experimental JIT (Just-In-Time) compiler. It also makes deferred evaluation of type annotations the default, which significantly speeds up startup times.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go 1.26:&lt;/strong&gt; The latest release makes the highly efficient &lt;strong&gt;Green Tea garbage collector&lt;/strong&gt; the default (reducing runtime overhead by up to about 40%) and introduces syntax quality-of-life updates, like allowing expressions directly inside the new() function for cleaner pointer creation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Core Differences&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before learning both languages, you first need to understand how they “think” differently:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How They Run&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Python runs your code line by line while the program is executing. This makes it flexible, easy to test quickly, and great for fast development.&lt;/p&gt;

&lt;p&gt;Go converts your code into a standalone executable file before it runs. Because of this, Go programs are usually much faster and more efficient.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How Programs Start&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In Python, you can usually just write code from top to bottom and run the file.&lt;/p&gt;

&lt;p&gt;In Go, every runnable program must follow a fixed structure. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;code&gt;package main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;and a &lt;code&gt;func main()&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That &lt;code&gt;main()&lt;/code&gt; function is where the program officially starts running.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Code Style and Formatting&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Python gives developers more freedom in how they write and organize code. There are style guides and formatting tools people commonly use, but they are mostly optional.&lt;/p&gt;

&lt;p&gt;Go is much stricter. It comes with its own formatting tool called &lt;code&gt;gofmt&lt;/code&gt;, and almost every Go developer uses it. This means most Go code looks very similar, making projects easier to read and maintain across teams.&lt;/p&gt;

&lt;p&gt;Over the next few weeks, I’ll be writing about Python and Go concepts, sharing code, and seeing what we can learn by comparing them side-by-side. I’d appreciate the support, so let me know what you feel or think about it.&lt;/p&gt;

&lt;p&gt;Let's Go Python! &lt;/p&gt;

</description>
      <category>go</category>
      <category>python</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Auth in 2026: What Actually Matters Now</title>
      <dc:creator>Ezeana Micheal</dc:creator>
      <pubDate>Mon, 11 May 2026 15:14:47 +0000</pubDate>
      <link>https://dev.to/ezeanamichael/auth-in-2026-what-actually-matters-now-32ac</link>
      <guid>https://dev.to/ezeanamichael/auth-in-2026-what-actually-matters-now-32ac</guid>
      <description>&lt;p&gt;With the speed at which Generative AI is being used to build applications, knowing how to code isn't the complete way anymore; understanding what to code is. What is needed? Why is it needed? and more. I’ve decided to take some level of these concepts and explain them to the best of my abilities. Starting with backend development. First, let's understand authentication and authorization concepts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt; is the process of confirming a user’s identity. Basically, it answers “Who is your user?”&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Authorization&lt;/strong&gt; is the process of confirming what a user can do. Basically, it answers “What can your user do?”&lt;/p&gt;

&lt;p&gt;In this article, I’ll write about different authentication and authorization methods, what instances they’re used in, and how they work.&lt;/p&gt;

&lt;p&gt;But first, we can’t talk about auths without mentioning passwords. Passwords are the most basic authentication method. But it is important to note, NEVER store passwords in plain text. It's the worst mistake any backend developer would make. The idea is to hash the passwords and verify the hash. There are many ways to hash a passwords, but here are 2 to avoid.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;MD5
&lt;/li&gt;
&lt;li&gt;SHA-256&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Why avoid them?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;These general-purpose hash functions are designed to be fast, and an attacker with a modern GPU can compute millions of SHA-256 per second, making attacks computationally cheap, so when selecting hashing algorithms for passwords, they have to be &lt;strong&gt;deliberately expensive or slow&lt;/strong&gt;. The 2 widely used are &lt;strong&gt;Bcrypt&lt;/strong&gt; and &lt;strong&gt;Argon2&lt;/strong&gt;. Both are designed to be slow and computationally expensive, making it harder for attackers to decipher them through brute-force attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bcrypt&lt;/strong&gt; was designed in 1999; it is based on the Blowfish cipher and uses a salt to protect against rainbow table attacks. It also incorporates a cost factor that quantifies the hash's computational cost. The cost doubles with each increment, i.e., cost 10 is twice as expensive or hard as cost 9 was.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Argon2&lt;/strong&gt; was introduced in 2015 as the winner of the Password Hashing Competition. The edge it has over bcrypt is that it has resistance to side-channel attacks. You can read more on it later.&lt;/p&gt;

&lt;p&gt;We will consider the following  authentication methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JWT Authentication
&lt;/li&gt;
&lt;li&gt;Session-Based Authentication
&lt;/li&gt;
&lt;li&gt;OpenID Connect Authentication
&lt;/li&gt;
&lt;li&gt;MFA (Multi-Factor Authentication)
&lt;/li&gt;
&lt;li&gt;SSO (Single Sign-On)
&lt;/li&gt;
&lt;li&gt;Passkeys / WebAuthn (FIDO2)
&lt;/li&gt;
&lt;li&gt;API keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the following authorization methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth 2.0
&lt;/li&gt;
&lt;li&gt;RBAC(Role-Based Access Control)
&lt;/li&gt;
&lt;li&gt;ABAC(Attribute-Based Access Control)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Starting with authentication,&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;JWT Authentication&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Json Web Token(JWT) is a compact, URL-safe token that encodes a set of claims (key-value pairs) and is cryptographically signed. A unique feature is that JWTs enable stateless authentication; the signature is verifiable without a database lookup. The server can validate the token with just the secret key.  &lt;/p&gt;

&lt;p&gt;A JWT has 3 Base64URL-encoded parts separated by dots: Header, Payload, and Signature.   &lt;/p&gt;

&lt;p&gt;a. Header contains the algorithm and the type e.g &lt;/p&gt;

&lt;p&gt;{ "alg": "HS256", "typ": "JWT" }&lt;/p&gt;

&lt;p&gt;b. Payload contains the encoded claims, e.g &lt;/p&gt;

&lt;p&gt;{&lt;br&gt;&lt;br&gt;
     "sub": "user_id_123",&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "email": "mike@synoloop.com",

 "role": "admin",

 "iat": 1716000000,    // issued at (Unix timestamp)

 "exp": 1716003600     // expires at (1 hour later) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;c. The signature is the encrypted base64url header and payload with the secret.&lt;/p&gt;

&lt;p&gt;In real-world authentication systems, JWTs are most commonly used in two forms: &lt;strong&gt;Access tokens&lt;/strong&gt; and &lt;strong&gt;refresh tokens&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Access tokens are short-lived, between 5 and 15 minutes. Refresh tokens, on the other hand, are long-lived from days to even weeks and are used to obtain new access tokens without reauthenticating (depending on the developer).&lt;/p&gt;

&lt;p&gt;But what happens if a token is stolen or a user logs out of the system? Since JWTs are stateless and valid until they expire, we need a way to &lt;em&gt;invalidate&lt;/em&gt; them before their natural expiration. This is where &lt;strong&gt;token blacklisting&lt;/strong&gt; comes in.&lt;br&gt;&lt;br&gt;
This is solved by maintaining a server-side denylist. Once any of the above events happen, the JWTID is added to the blacklist.&lt;/p&gt;

&lt;p&gt;So on logout or password change or compromise, it's best to revoke or blacklist all existing refresh tokens. This logs out the user on all sessions. On each request, the server looks up the session ID, retrieves the session data, and authenticates the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Session-Based Authentication&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Session-based authentication stores the auth state on the server, so when a user logs in, it creates a session record and stores it. What makes Sessions different from JWTs is that Sessions are easier to revoke immediately, but require server-side storage. JWTs are stateless but harder to invalidate before expiry.  &lt;/p&gt;

&lt;p&gt;In sessions, it's best to always regenerate the session ID after login to prevent session fixation attacks.  &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;OpenID Connect (OIDC) Authentication&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OIDC is an identity layer built on top of OAuth 2.0(Will be discussed in authorization). OIDC answers who this user is. It adds a standardized ID token(a JWT) containing identity claims.  &lt;/p&gt;

&lt;p&gt;Think of this as when you use any web application that has a “continue with Google”; this sends your name, email, phone (and other details if requested) from Google to the web application authorized, answering who you are.  &lt;/p&gt;

&lt;p&gt;It gives the addition of what an OAuth 2.0 gives.   &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ID Token: a JWT containing user identity (sub, email, name, picture, etc.)
&lt;/li&gt;
&lt;li&gt;UserInfo Endpoint: returns additional claims about the authenticated user
&lt;/li&gt;
&lt;li&gt;Discovery Document: /.well-known/openid-configuration for automatic configuration
&lt;/li&gt;
&lt;li&gt;Standard Claims: sub (subject/user ID), email, email_verified, name, picture&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;MFA( Multi-Factor Authentication)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Multi-factor authentication requires users to have two or more verification factors present: something they know (password), something they have (phone/hardware key), and something they are (biometric).  &lt;/p&gt;

&lt;p&gt;Multi-factor authentication includes methods like TOTP and Backup Codes.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;TOTP(Time-Based One-Time Passwords), generates a 6-digit code that changes every 30 seconds based on a shared secret and the current time. It works with apps like Google Authenticator, Microsoft Authenticator, and such.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backup Codes: These are a list of 8 to 10 single-use random codes that can be used to retrieve the account or authenticate.  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;SSO(Single Sign-On)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Single Sign-On allows users to authenticate once and gain access to multiple systems. This is mostly used in enterprise environments or applications; the 2 main protocols are SAML 2.0 (XML-based, older) and OIDC-based SSO (modern, JSON/JWT-based).  &lt;/p&gt;

&lt;p&gt;SAML is the standard in enterprise environments (corporate identity providers like Okta and Azure). It uses XML assertions to tell the identity. The identity provider (IdP) authenticates the user and sends a signed XML assertion to the service provider (SP).  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Service Provider (SP) is your application
&lt;/li&gt;
&lt;li&gt;Identity Provider (IdP) is Okta, Azure, Google Workspace, etc.
&lt;/li&gt;
&lt;li&gt;An assertion is a signed XML document asserting identity and attributes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Passkeys / WebAuthn (FIDO2)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Passkeys are an advanced form of authentication: passwordless, phishing-resistant, and cryptographically strong. Based on the WebAuthn standard (W3C) and FIDO2 protocol, they use public-key cryptography with biometrics or device PINs.  &lt;/p&gt;

&lt;p&gt;Passkeys have become popular since their release in 2018. They work in 2 major steps:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Registration: The browser or the device generates a public/private key pair. Private key stays on the device. The public key is sent to your server.
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Authentication: Server sends a challenge. The device signs the challenge with the private key. The server verifies with the stored public key.&lt;/p&gt;

&lt;p&gt;No Password is ever transmitted or stored, and attackers can’t do anything with just the public key.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;API keys&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I chose to keep API keys under authentication, but underneath, they do both authentication and authorization; I’ll explain.&lt;br&gt;&lt;br&gt;
   API keys are Opaque tokens issued for programmatic access to services, scripts or public-facing APIs.They should be scoped, rotatable, and auditable.  &lt;/p&gt;

&lt;p&gt;API keys act like a username and password pair, but simplified. They identify the calling application or developer. For example, A weather API requires an API key to ensure only registered apps can access data.  &lt;/p&gt;

&lt;p&gt;While some APIs use keys with scoped permissions (e.g., read-only or read and write).&lt;br&gt;&lt;br&gt;
   &lt;strong&gt;Example:&lt;/strong&gt; A developer can generate API keys in a payment app and may allow one key to process transactions but another only to view reports.   &lt;/p&gt;

&lt;p&gt;Some design principles of API keys include:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Including a prefix for easy identification (e.g., sk_live_, sk_test_, syno_)
&lt;/li&gt;
&lt;li&gt;Generate with cryptographically secure randomness (at least 128 bits)
&lt;/li&gt;
&lt;li&gt;Store only the hash in your database, treat keys like passwords
&lt;/li&gt;
&lt;li&gt;Support scopes/permissions per key
&lt;/li&gt;
&lt;li&gt;Log all usage with timestamps for auditing
&lt;/li&gt;
&lt;li&gt;Support rotation: allow multiple active keys per user, then invalidate old ones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's consider &lt;strong&gt;the authorization concepts&lt;/strong&gt;:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;OAuth 2.0&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is an authorization framework that allows a third-party application to obtain limited access to a service on a user's behalf without exposing credentials. You can think of this as “connect to GitHub” or authorizing Google Drive access via a “connect to Google.” It's about what you can access, not about who you are.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;RBAC(Role-Based Access Control)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;RBAC Controls access by assigning permissions to roles, and roles to users. This is most common in authorization models for web applications. User has a role, and the role has permissions. For example, in an e-commerce application. There are key roles like Admin, Vendor, and User. Each of these roles has different permissions. Admin can read all users and vendors, edit or verify, or ban a vendor. The vendor can upload products, the user can read and purchase products.   &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ABAC(Attribute-Based Access Control)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;ABAC is another authorization method. It evaluates attributes of the user, the resource, the action, and the environment to make an authorization decision. For example, consider that &lt;strong&gt;a manager&lt;/strong&gt; can &lt;strong&gt;edit&lt;/strong&gt; a document &lt;strong&gt;only if they are in the same department&lt;/strong&gt; as the document's owner, &lt;strong&gt;during business hours&lt;/strong&gt;. We can see that many conditions affect the action that can be carried out by the manager.  &lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use ABAC vs RBAC
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use RBAC when access rules map cleanly to roles and don't depend on resource data
&lt;/li&gt;
&lt;li&gt;Use ABAC when you need fine-grained rules like row-level security, ownership checks, or time-based restrictions
&lt;/li&gt;
&lt;li&gt;Many systems use both: RBAC as a coarse gate, ABAC for fine-grained resource access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the conclusion of my article. We’ve considered various authentication and authorization concepts.&lt;br&gt;&lt;br&gt;
Please show your appreciation by giving this a &lt;strong&gt;like&lt;/strong&gt;, leaving a &lt;strong&gt;comment&lt;/strong&gt; with something encouraging, or sharing something you just learned, or something I may have gotten wrong. Thanks for reading.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>database</category>
      <category>writing</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
