<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kin NG</title>
    <description>The latest articles on Forem by Kin NG (@k1nho).</description>
    <link>https://forem.com/k1nho</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1134927%2F960ca343-a06e-49c9-9263-53f288dd6a02.jpeg</url>
      <title>Forem: Kin NG</title>
      <link>https://forem.com/k1nho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/k1nho"/>
    <language>en</language>
    <item>
      <title>A 💯 Days in Open Source: Key Lessons That Will Help You Get Started 🚀</title>
      <dc:creator>Kin NG</dc:creator>
      <pubDate>Mon, 20 Nov 2023 16:47:39 +0000</pubDate>
      <link>https://forem.com/k1nho/a-days-in-open-source-key-lessons-that-will-help-you-get-started-4e38</link>
      <guid>https://forem.com/k1nho/a-days-in-open-source-key-lessons-that-will-help-you-get-started-4e38</guid>
      <description>&lt;p&gt;October 31st marked the end of the 100 days of open source software (&lt;strong&gt;OSS&lt;/strong&gt;) challenge by &lt;a href="https://opensauced.pizza/" rel="noopener noreferrer"&gt;Open Sauced&lt;/a&gt;. This challenge aimed to unite newcomers, dedicated contributors, and maintainers within OSS projects to foster active involvement, learn new skills, and enhance community interaction by engaging in OSS for 100 days. As a participant of this challenge, I will share three significant lessons I learned from this experience to help newcomers in getting started with OSS and making meaningful contributions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source is Scary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxg03zrvm5fh3zpr091d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxg03zrvm5fh3zpr091d.gif" alt="Courage Cowardly Dog in Computer" width="500" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From an outsider's perspective, getting involved in open source software can seem intimidating. This feeling can be attributed to various factors, but the most common ones I've seen and personally experienced are &lt;strong&gt;fear of the unknown&lt;/strong&gt;, &lt;strong&gt;mastering technologies&lt;/strong&gt;, and &lt;strong&gt;receiving feedback&lt;/strong&gt;. Let's break down each of these challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fear of The Unknown
&lt;/h2&gt;

&lt;p&gt;It's no secret that when you first dive into a new repository, you won't know everything about it. It might cover a specific software area you are unfamiliar with, or it might introduce you to concepts you've never encountered. This fear of the unknown can be paralyzing, leading to a point where some may give up without even trying.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8cikfaqs11listac35f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8cikfaqs11listac35f.gif" alt="Shin chan question" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;
&lt;p&gt;
&lt;em&gt;exploring a CNCF codebase be like&lt;/em&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;Recognizing the dynamic nature of software is the first step in accepting the presence of inherent unknowns. The key is not to let fear hold you back. Begin by exploring the codebase in small steps, such as reading the documentation or running the project locally. If you encounter a part of the codebase that seems puzzling, remember that most OSS projects have active communities willing to provide support and help you gain a better understanding.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Embrace the fact that there will always be unknowns in OSS. Start small, run the project, and gradually piece together how it works. Leveraging the community is a valuable resource to accelerate your learning.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Mastery of Technologies
&lt;/h2&gt;

&lt;p&gt;In addition to dealing with the unknown, effective participation in OSS often requires proficiency in certain technologies. Given the collaborative nature of OSS, a distributed version control system like &lt;a href="https://en.wikipedia.org/wiki/Git" rel="noopener noreferrer"&gt;Git&lt;/a&gt; is an essential tool for tracking file changes. Thus, it is important to have Git in your arsenal, since it is highly likely that a project you engage with in the OSS community will leverage Git for version control. If you're new to Git or want to brush up on the basics for OSS contributions, I highly recommend the &lt;a href="https://intro.opensauced.pizza/#/" rel="noopener noreferrer"&gt;Intro to Open Source course by Open Sauced&lt;/a&gt;. It covers everything from the history of OSS to Git usage and types of contributions that will help you get started.&lt;/p&gt;

&lt;p&gt;Once you've used Git, you'll face the challenge of learning specific technologies, usually a programming language. When starting your journey in OSS, it's beneficial to choose repositories aligned with your technical abilities. For example, if you are proficient in &lt;a href="https://www.w3schools.com/python/python_intro.asp" rel="noopener noreferrer"&gt;Python&lt;/a&gt;, you should aim to select repositories whose codebase is mostly written in Python. Additionally, if you know multiple languages, you could help with the translations of the project's documentation to those languages. &lt;/p&gt;

&lt;p&gt;Familiarity with the technologies used in a project can expedite your understanding of the codebase, making it easier to contribute without simultaneously learning a new technology. However, there's also value in stepping out of your comfort zone and tackling repositories that introduce you to unfamiliar technologies. In such cases, opt for smaller codebases that are more digestible. Lack of complete mastery of a particular technology should not deter you from contributing to OSS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pick a repository with technologies you already know; this will help you to bridge gaps of knowledge faster, and avoid learning while exploring. If you pick a technology that you don't know and want to challenge yourself, start with small repositories as this will give you enough time to learn outside of exploration.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Receiving Feedback
&lt;/h2&gt;

&lt;p&gt;Last but certainly not least is the challenge of receiving feedback. If it's not a lack of skills or fear of the unknown that hinders contributors, what could it be? OSS is inherently collaborative, and effective communication is crucial. After you tackle an issue and submit a pull request, you'll likely receive feedback from the maintainer and reviewers. While some contributors may interpret feedback as a sign of their contributions being inadequate, this is often not the case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feksp137cc95h53wgukkl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feksp137cc95h53wgukkl.gif" alt="Chansey pokemon reading" width="480" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;
&lt;p&gt;
&lt;em&gt;nit: racecar should be racecar&lt;/em&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;OSS projects adhere to certain standards, and it's the maintainer's responsibility to ensure that contributions benefit the project, its users, and future contributors. Receiving feedback provides you with an opportunity to improve your coding skills and communication. In some instances, however, you may encounter less-friendly maintainers, and it's essential to recognize when it is better to move on.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Treat feedback as an opportunity to enhance your technical skills and engage in effective communication with the maintainer to address any concerns. If you don't feel comfortable in a particular community, don't hesitate to explore other options.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Defining Open Source Goals
&lt;/h2&gt;

&lt;p&gt;The question of why you should participate in OSS remains, and your motivations can vary widely. That's why it is crucial to &lt;a href="https://dev.to/opensauced/setting-goals-for-your-open-source-contributions-349b"&gt;set goals for your OSS contributions&lt;/a&gt;. Your objectives may include acquiring new skills, getting involved in exciting projects, seeking mentorship, or connecting with like-minded individuals who share your passion. You might even be contemplating becoming a maintainer to gain support for your own projects.&lt;/p&gt;

&lt;p&gt;Regardless of your specific goals, I firmly believe that engaging in Open Source can bring invaluable benefits to your skills, and I hope that this article has provided valuable insights to help you start your journey into OSS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mefae8lq84cjjrzyfao.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mefae8lq84cjjrzyfao.gif" alt="Matsuoka Shuzo Never Give Up" width="498" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Get started with OSS here: &lt;a href="https://intro.opensauced.pizza/#/" rel="noopener noreferrer"&gt;&lt;strong&gt;Open Sauced Intro to OSS Course&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Looking for your first contribution? check these &lt;a href="https://app.opensauced.pizza/pages/BekahHW/655/dashboard?range=30" rel="noopener noreferrer"&gt;&lt;strong&gt;repositories for beginners&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opensauced.pizza/" rel="noopener noreferrer"&gt;&lt;strong&gt;Open Sauced&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hacktoberfest.com/participation/" rel="noopener noreferrer"&gt;&lt;strong&gt;Hacktoberfest&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Links:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Connect with me on Github: &lt;a href="//github.com/k1nho"&gt;&lt;strong&gt;github.com/k1nho&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Open Source: &lt;a href="https://app.opensauced.pizza/user/k1nho?tab=highlights" rel="noopener noreferrer"&gt;&lt;strong&gt;opensauced/k1nho&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect with me on X: &lt;a href="https://twitter.com/Kinho_nth" rel="noopener noreferrer"&gt;&lt;strong&gt;@Kinho_nth&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>100daysofoss</category>
    </item>
    <item>
      <title>You Might be Overlooking the PUT Method in Your REST API</title>
      <dc:creator>Kin NG</dc:creator>
      <pubDate>Tue, 08 Aug 2023 17:32:11 +0000</pubDate>
      <link>https://forem.com/k1nho/you-might-be-overlooking-the-put-method-in-your-rest-api-2b1h</link>
      <guid>https://forem.com/k1nho/you-might-be-overlooking-the-put-method-in-your-rest-api-2b1h</guid>
      <description>&lt;p&gt;So, you’re building your first or maybe your hundredth REST API, or perhaps you’re following along with a tutorial, and you’re about to implement the PUT HTTP method for an endpoint. To demonstrate a simple workflow for implementing a PUT endpoint, let’s take a look at the following code snippets. In this article, I will be using Golang, but you can follow along with the language of your choice. Consider the following schema for a Pokemons table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;pokemons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;bigserial&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="k"&gt;zone&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;NO&lt;/span&gt;
    &lt;span class="n"&gt;atk&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, for the server logic, we will first invoke our GET method to retrieve the Pokémon that the user wants to update, like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PokemonModel&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;PokemonModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Pokemon&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;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ErrRecordNotFound&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`
        SELECT id, created_at, name, region, atk, def
        FROM pokemons
        WHERE id=$1
    `&lt;/span&gt;

 &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt; &lt;span class="n"&gt;Pokemon&lt;/span&gt;

 &lt;span class="c"&gt;// Context to cancel our query, if it takes more than 3 seconds&lt;/span&gt;
 &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

 &lt;span class="c"&gt;// Query the database and read the record into our pokemon struct&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;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRowContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreatedAt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
           &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Def&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&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="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNoRows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ErrRecordNotFound&lt;/span&gt;
  &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we create an update method that will be invoked with the Pokémon retrieved from the GET method to finalize the update.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;PokemonModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Pokemon&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="c"&gt;// update SQL query&lt;/span&gt;
 &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`
        UPDATE pokemons
        SET name=$1, region=$2, atk=$3, def=$4
        WHERE id=$5
        RETURNING id
    `&lt;/span&gt;

 &lt;span class="c"&gt;// The values of our placeholder parameters&lt;/span&gt;
 &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                       &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Def&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="c"&gt;// Context to cancel our query, if it takes more than 3 seconds&lt;/span&gt;
 &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

 &lt;span class="c"&gt;// return the result of the update query (nil if no err, otherwise err)&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRowContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Nice! We're done, right? Surely, there's no problem with this simple update. Well, what if I told you that you are about to fall into a &lt;strong&gt;data race&lt;/strong&gt; - one of the most common and often overlooked problems when performing updates on a mutable shared resource. Our Pokémon record is a shared resource that can be accessed by two or more threads simultaneously. Therefore, the order of operations, as it stands, is dependent on the exact order in which the scheduler executes instructions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk56use1c7t42j13l3vzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk56use1c7t42j13l3vzc.png" alt="Data race example" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above diagram, Alice makes a GET request (&lt;strong&gt;api/pokemons/376&lt;/strong&gt;) and obtains the record of the Pokémon with id=376. Similarly, Bob also makes the same GET request. At this point in time, both Alice and Bob have the Pokémon record represented by the green box, and a data race is about to occur when they both attempt to modify the original green record by sending a PUT request at approximately the same time.&lt;/p&gt;

&lt;p&gt;In this scenario, Bob wants to change the &lt;strong&gt;def field to 400&lt;/strong&gt;, while Alice wants to change the &lt;strong&gt;atk field to 330&lt;/strong&gt;. However, as illustrated, only Alice's request is processed, resulting in the final green box representing only Alice's update. Ideally, the record should have contained both updates instead of just Alice's. However, due to the requests being processed at around the same time, the scheduler has decided to apply Alice's update after Bob's, making Bob's request a victim of the data race.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Deal with the Data Race ?
&lt;/h2&gt;

&lt;p&gt;There are multiple ways to address a data race, but the two main approaches are &lt;a href="https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking" rel="noopener noreferrer"&gt;pessimistic locking and optimistic locking&lt;/a&gt;. In our case, we will utilize optimistic locking to handle the data race. To protect our Pokémon record from a data race condition using optimistic locking, the following changes need to be implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Version Column to the Pokemons Table
&lt;/h3&gt;

&lt;p&gt;The first step to address the data race using optimistic locking, is to add a version column to our pokemons table. The version number will be defaulted to 1, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;pokemons&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Include the Version Field in the Queries
&lt;/h3&gt;

&lt;p&gt;Now, we need to include the version field in our queries. For the GET method will include version to the list of fields to be returned from the query.&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;query&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`
        SELECT id, created_at, name, region, atk, def, version
        FROM pokemons
        WHERE id=$1
    `&lt;/span&gt;
&lt;span class="c"&gt;// Pass version as well to be stored in the struct (&amp;amp;pokemon.Version)&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;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRowContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreatedAt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Def&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Update method will be slightly different. When making an update, we need to ensure that we increment the version number by 1, while simultaneously checking that the version number has not changed since we sent the GET request.&lt;/p&gt;

&lt;p&gt;By increasing the version number by 1, we guarantee a unique, monotonically increasing column that can be checked against any other simultaneous queries. Including the version number in the conditional check ensures that we don't make changes to a record that was modified during the transaction.&lt;/p&gt;

&lt;p&gt;The full code for the Update method now 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="c"&gt;// Custom error to notify of a data race&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ErrEditConflict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"edit conflict"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;PokemonModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Pokemon&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="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`
        UPDATE pokemons
        SET name=$1, region=$2, atk=$3, def=$4, version=version+1
        WHERE id=$5 AND version=$6
        RETURNING version
    `&lt;/span&gt;

 &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                       &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Def&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&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;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryRowContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&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="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNoRows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ErrEditConflict&lt;/span&gt;
  &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now that we have handled the data race, one possible follow-up is to make use of a custom error, such as &lt;strong&gt;ErrEditConflict&lt;/strong&gt;, to send this event through an event queue and retry the failed query in a background worker. Regardless of the specific way you choose to deal with the conflict, the important thing is that you have taken action to solve the data race, and that is commendable.&lt;/p&gt;

&lt;p&gt;Even though this is a simple example and the conflict may not seem harmful, it's crucial to recognize that such errors can lead to devastating consequences. For instance, when dealing with updates to an account's balance. Nevertheless, I hope this article has been helpful to you and has made you aware of the potential errors that can arise when implementing the PUT HTTP method in REST APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lets-go-further.alexedwards.net/" rel="noopener noreferrer"&gt;&lt;strong&gt;Let's Go Further By Alex Edwards. Chapter 6&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Race_condition#Data_race" rel="noopener noreferrer"&gt;&lt;strong&gt;Data Race&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking" rel="noopener noreferrer"&gt;&lt;strong&gt;Optimistic locking vs Pessimistic locking&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Links:
&lt;/h3&gt;

&lt;p&gt;Github: &lt;a href="//github.com/k1nho"&gt;&lt;strong&gt;github.com/k1nho&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
Twitter: &lt;a href="https://twitter.com/Kinho_nth" rel="noopener noreferrer"&gt;&lt;strong&gt;@Kinho_nth&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

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