<?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: LinceMathew</title>
    <description>The latest articles on Forem by LinceMathew (@lincemathew).</description>
    <link>https://forem.com/lincemathew</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%2F1138237%2F84b2cb1c-8fe3-4f02-bbea-4edd8de7c7b7.jpeg</url>
      <title>Forem: LinceMathew</title>
      <link>https://forem.com/lincemathew</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lincemathew"/>
    <language>en</language>
    <item>
      <title>Automate the Boring Stuff! Check Out This Open-Source Tool</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Sun, 13 Jul 2025 16:09:50 +0000</pubDate>
      <link>https://forem.com/lincemathew/automate-the-boring-stuff-check-out-this-open-source-tool-5efk</link>
      <guid>https://forem.com/lincemathew/automate-the-boring-stuff-check-out-this-open-source-tool-5efk</guid>
      <description>&lt;p&gt;If you’re tired of doing the same tasks over and over—copying data between apps, checking emails, or updating spreadsheets—there’s a better way. Meet n8n, a tool that helps you automate those repetitive jobs without needing to be a programmer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/n8n-io/n8n" rel="noopener noreferrer"&gt;n8n stands for Node Automation&lt;/a&gt;. It’s an open-source platform that lets you connect different apps, move data between them, and build powerful automations.&lt;/p&gt;

&lt;p&gt;You can think of it like Zapier, but with more flexibility. Plus, you can host it yourself, which means more control and no monthly fees.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set It Up, No Sweat
&lt;/h2&gt;

&lt;p&gt;Getting started with n8n is simple, and there are a few different ways to run it depending on your preference. Whether you're just trying it out or setting it up for daily use, here are your options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Run n8n with Docker&lt;/strong&gt;&lt;br&gt;
If you have Docker installed, this is one of the easiest and cleanest ways to run n8n. Open your terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 5678:5678 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; ~/.n8n:/home/node/.n8n &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;N8N_BASIC_AUTH_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;user &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;N8N_BASIC_AUTH_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pass &lt;span class="se"&gt;\&lt;/span&gt;
  n8nio/n8n

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

&lt;/div&gt;



&lt;p&gt;This will start n8n on port 5678 with basic username and password protection. Your workflows will be saved in your local .n8n folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Use npx to Try n8n Instantly&lt;/strong&gt;&lt;br&gt;
If you have Node.js, you can launch it using just one command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That’s it—no setup, no extra install. It’s great for quick testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Your First Workflow
&lt;/h2&gt;

&lt;p&gt;In this example, we’ll create an automation that fetches the &lt;a href="https://github.com/trending" rel="noopener noreferrer"&gt;daily trending&lt;/a&gt; Go (Golang) repositories on GitHub and adds them to a Google Sheets spreadsheet. This shows how n8n can help you collect and organize information automatically.&lt;/p&gt;

&lt;p&gt;In n8n, a &lt;strong&gt;workflow&lt;/strong&gt; is a series of connected tasks that run automatically, and each task is called a &lt;strong&gt;node&lt;/strong&gt;. Nodes perform specific actions like getting data, processing it, or saving results.&lt;/p&gt;

&lt;p&gt;Here’s a quick look at the workflow we’ll build:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cron Node:&lt;/strong&gt; This triggers the workflow to run once every day (or whenever you want).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP Request Node&lt;/strong&gt;: It fetches the trending repositories page from GitHub for the Go language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTML Extract Node:&lt;/strong&gt; This node reads the web page and pulls out the repository names and descriptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function Node:&lt;/strong&gt; It organizes the data into a clean format with title, description, and URL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google Sheets Node:&lt;/strong&gt; Finally, this node adds the data into a Google Sheets spreadsheet.&lt;/p&gt;

&lt;p&gt;Next, we’ll walk through each step so you can build this workflow yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before building the workflow, make sure you have a Google Sheet ready. The first row (header) of the sheet should have these three columns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Title | Description | URL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need to authorize Google Sheets in n8n. To do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to Credentials → Google Sheets OAuth2 in n8n.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a Google Cloud project and set up an OAuth Client ID.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add these credentials to the Google Sheets node in your workflow.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Febex1w7tv0c3u5zgyhdm.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%2Febex1w7tv0c3u5zgyhdm.png" alt=" " width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cron Node — Trigger Your Workflow
&lt;/h3&gt;

&lt;p&gt;The Cron node triggers your workflow based on time. You can set it to run daily, hourly, or whenever you want. For this example, set it to run once a day.&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%2F5t55vidy0vxo965jo3q2.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%2F5t55vidy0vxo965jo3q2.png" alt=" " width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. HTTP Request Node — Fetch GitHub Trending Repos
&lt;/h3&gt;

&lt;p&gt;This node sends a GET request to GitHub’s trending page for Go repositories. The URL is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://github.com/trending/go?since&lt;span class="o"&gt;=&lt;/span&gt;daily
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can replace go with any language you want to track. The response will be the page’s HTML in text format.&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%2Fkc80vzdgoac5p4dk6dm9.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%2Fkc80vzdgoac5p4dk6dm9.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. HTML Extract Node — Get Repo Names and Descriptions
&lt;/h3&gt;

&lt;p&gt;The HTML Extract node reads the page’s HTML and extracts the repository names and descriptions using CSS selectors.&lt;/p&gt;

&lt;p&gt;For repo names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="nc"&gt;.Box-row&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="nc"&gt;.Box-row&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The node uses the HTML body from the HTTP Request node as input.&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%2Ffi69jg7su6gg80j1u8tf.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%2Ffi69jg7su6gg80j1u8tf.png" alt=" " width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Function Node — Format Data for Google Sheets
&lt;/h3&gt;

&lt;p&gt;This node takes the extracted data and cleans it up. It trims extra spaces and creates a neat JSON object with three fields: Title, Description, and URL. The URL is built by adding &lt;a href="https://github.com" rel="noopener noreferrer"&gt;https://github.com&lt;/a&gt; in front of the repo name.&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%2F4lxd0mx8msk2zy0g7tji.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%2F4lxd0mx8msk2zy0g7tji.png" alt=" " width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Google Sheets Node — Save Data to Your Sheet
&lt;/h3&gt;

&lt;p&gt;Finally, this node adds the formatted data to your Google Sheet. Use the Append operation and specify your sheet’s ID and the range (for example, Sheet1!A:C). Map the fields Title, Description, and URL to the corresponding columns in your sheet.&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%2Fzoo3dmtwwnoxj6icfga9.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%2Fzoo3dmtwwnoxj6icfga9.png" alt=" " width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how our final workflow looks.&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%2F6a6wenc95enj7dy511c4.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%2F6a6wenc95enj7dy511c4.png" alt=" " width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s trigger the workflow manually.&lt;br&gt;
Boom! All the trending Go repositories from GitHub are added to our Google Sheet!&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%2Fd21i2l23oworqkrcpwd3.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%2Fd21i2l23oworqkrcpwd3.png" alt=" " width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Else Can You Automate with n8n?
&lt;/h2&gt;

&lt;p&gt;n8n is very flexible and can help automate many everyday tasks. Here are some common ways people use it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notifications&lt;/strong&gt;&lt;br&gt;
For example, when a new order comes in, n8n can automatically send a message to your team on Slack and send an email alert. This keeps everyone updated without manual effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reporting&lt;/strong&gt;&lt;br&gt;
You can gather important data or metrics every week, create a report, and have n8n email it to your team before meetings. This saves time and ensures everyone has the latest information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Scraping&lt;/strong&gt;&lt;br&gt;
Want to track competitor prices? n8n can scrape product prices from websites and log the data into a Google Sheet for easy comparison.&lt;/p&gt;

&lt;p&gt;These examples show just a few of the many ways n8n can simplify your work by automating repetitive tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line: Is n8n for You?
&lt;/h2&gt;

&lt;p&gt;If you find yourself doing the same tasks over and over—copying data, sending emails, checking updates—n8n can save you a lot of time. It’s powerful, flexible, and doesn’t require you to be a developer.&lt;/p&gt;

&lt;p&gt;Whether you're automating small personal tasks or building complex workflows for your team, n8n makes it easier. And the best part? You’re in full control, especially if you choose to self-host it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PRO TIP: Struggling to locate API endpoints across your codebase?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hexmos.com/landing/liveapi" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt; lets you instantly find and explore every endpoint across all your repositories — give it a try and see how much easier navigation can be!&lt;/p&gt;

</description>
      <category>automation</category>
      <category>opensource</category>
      <category>n8n</category>
    </item>
    <item>
      <title>Getting the Best Out of GitHub Copilot</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Sun, 01 Jun 2025 16:20:14 +0000</pubDate>
      <link>https://forem.com/lincemathew/getting-the-best-out-of-github-copilot-ejc</link>
      <guid>https://forem.com/lincemathew/getting-the-best-out-of-github-copilot-ejc</guid>
      <description>&lt;p&gt;As my first in-editor AI coding partner, I started with &lt;a href="https://www.cursor.com/" rel="noopener noreferrer"&gt;Cursor&lt;/a&gt;. However, four months ago, I decided to switch to &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;. While using Cursor, I was aware of Copilot and its features, but at the time, it felt unstable and not as polished as Cursor. Recently, I noticed that GitHub Copilot has been improving significantly, becoming a strong competitor to Cursor. This encouraged me to give Copilot a try, especially since it offers a larger quota for expensive LLM calls and has proven to be stable even in its preview version.&lt;/p&gt;

&lt;p&gt;Another reason for the switch was my existing GitHub Pro subscription, which meant I could save $22 per month by not needing Cursor’s subscription if Copilot proved to be a good alternative.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore some of unique Copilot’s features i found and best practices we can use to make the best out of copilot.&lt;br&gt;
FYI:My primary focus is on Github copilot extension on &lt;a href="https://visualstudio.microsoft.com/github-copilot/" rel="noopener noreferrer"&gt;VScode insider&lt;/a&gt;, even you can access copilot from web version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personalizing GitHub Copilot Responses
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot allows you to customize its responses to better suit your needs.Its difficult and irritating to mention stick to functional programming, use early return etc in every chat completion. These custom instructions help Copilot understand your preferences, project requirements, or even organization-wide standards. There are three types of custom instructions you can use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Personal Custom Instructions&lt;/strong&gt;: Copilot’s responses to your individual preferences across all conversations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository Custom Instructions&lt;/strong&gt;: Define project-specific guidelines, frameworks, or coding standards for a particular repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization Custom Instructions&lt;/strong&gt;: Apply organization-wide preferences, managed by organization owners, to ensure consistency across all repositories.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s start with personal custom instructions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Personal Custom Instructions
&lt;/h3&gt;

&lt;p&gt;Personal custom instructions let you customize how GitHub Copilot responds to you, making it more aligned with your preferences. Setting them up is straightforward and can be done either in the Copilot Chat panel or immersive mode.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to Add Personal Instructions
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open the Copilot Chat panel or immersive mode:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Click the Copilot Chat icon in the top-right corner of any GitHub page to open the panel.&lt;/li&gt;
&lt;li&gt;If you prefer a full-page view, click the dropdown next to the Copilot Chat icon and select "Immersive." You can also go directly to &lt;a href="https://github.com/copilot" rel="noopener noreferrer"&gt;https://github.com/copilot&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Access Personal Instructions:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;In the Chat panel or immersive page, click the dropdown menu at the top-right corner and select "Personal instructions."&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add Your Preferences:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Write your preferences in the text box using natural language. You can format them however you like—either as a single block of text, line by line, or separated by blank lines.&lt;/li&gt;
&lt;li&gt;If you’re unsure where to start, click the templates button to see examples of common instructions. For instance, selecting "Communication" will add placeholders like &lt;code&gt;{format}&lt;/code&gt; that you can customize.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Save Your Instructions:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Click "Save" to activate your instructions. They’ll stay active until you decide to change or remove them.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Let’s say you want Copilot to respond in Portuguese and keep explanations short and simple. Here’s how you can set it up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Copilot Chat panel.&lt;/li&gt;
&lt;li&gt;In the "Personal instructions" section, add the following:
Always respond in Portuguese. Keep explanations concise and break them down step by step.&lt;/li&gt;
&lt;li&gt;Save your instructions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, whenever you interact with Copilot, it will respond in Portuguese and provide clear, concise explanations tailored to your preferences.&lt;/p&gt;

&lt;p&gt;continue reading the &lt;a href="https://journal.hexmos.com/getting-the-best-out-of-github-copilot/" rel="noopener noreferrer"&gt;full article here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Data Races in Go: What They Are and Why You Should Care</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Sun, 13 Apr 2025 16:04:16 +0000</pubDate>
      <link>https://forem.com/lincemathew/data-races-in-go-what-they-are-and-why-you-should-care-14fa</link>
      <guid>https://forem.com/lincemathew/data-races-in-go-what-they-are-and-why-you-should-care-14fa</guid>
      <description>&lt;p&gt;A data race happens when two or more goroutines access the same memory location at the same time, and at least one of them writes to it — without proper synchronization.&lt;/p&gt;

&lt;p&gt;This can lead to unpredictable behavior. Your program might sometimes work just fine, and other times crash or return wrong results. That’s because the order in which goroutines run isn’t guaranteed, so without coordination, one goroutine might read a value while another is in the middle of changing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Are Data Races a Problem?
&lt;/h2&gt;

&lt;p&gt;Data races aren’t just theoretical—they can cause real, unpredictable problems that are difficult to catch and fix. Here’s a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;race&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;wait&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="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&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;n&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c"&gt;// read, increment, write&lt;/span&gt;
        &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c"&gt;// conflicting access&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, both the main goroutine and the anonymous goroutine are updating the same variable &lt;code&gt;n&lt;/code&gt;. Since there’s no coordination between them—no locks, no channels protecting the access—we don’t know which &lt;code&gt;n++&lt;/code&gt; happens first. The output might be 1, 2, or something even weirder depending on how the Go runtime schedules the goroutines.&lt;/p&gt;

&lt;p&gt;This is the essence of a data race: multiple goroutines accessing shared memory without synchronization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what’s the big deal?&lt;/strong&gt;&lt;br&gt;
The biggest problem with data races is that they don’t fail consistently. Your code might run fine 100 times and crash on the 101st. That makes them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Hard to reproduce&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard to debug&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy to miss in tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the impact can be serious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You might get incorrect results or corrupted state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Goroutines might get stuck in deadlocks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your program might even crash if memory is accessed in unsafe ways&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your app  "sometimes fails for no reason," a data race could be the hidden culprit.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Spot Data Races
&lt;/h2&gt;

&lt;p&gt;The good news? Go makes it easy to spot data races using a built-in tool: the &lt;a href="https://go.dev/doc/articles/race_detector" rel="noopener noreferrer"&gt;race detector&lt;/a&gt;.&lt;br&gt;
Let's try it out with our example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="n"&gt;counter&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;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="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="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;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c"&gt;// race condition&lt;/span&gt;
            &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="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;counter&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;Each goroutine tries to increment counter. But since there's no synchronization—no mutex, no channel—they can interfere with each other. The result is unpredictable, and chances are the final output won’t be 10.&lt;/p&gt;

&lt;p&gt;To catch this, run the program with Go’s race detector:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The -race flag enables Go’s runtime race detector. If there’s a data race, you’ll see a warning like this:&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%2Fh780elxiph8876qjy4s0.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%2Fh780elxiph8876qjy4s0.png" alt="Iription" width="711" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This output shows exactly where the race occurred, what variable was involved, and which goroutines were part of the conflict. It’s a powerful way to catch concurrency issues early—ideally before they make it into production.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Solve Data Races
&lt;/h2&gt;

&lt;p&gt;Once you’ve spotted a data race, the next step is fixing it. Go gives you three main tools for this: mutexes, atomic operations, and channels. Each has its place, depending on what you're doing and how you want to coordinate access to shared data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a Mutex
&lt;/h3&gt;

&lt;p&gt;A sync.Mutex ensures that only one goroutine can access a piece of code at a time. You lock before accessing the shared variable and unlock after you're done.&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;counter&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&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;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="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;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="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;"Counter:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&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 mutex (&lt;code&gt;mu&lt;/code&gt;) protects access to counter. Only one goroutine can increment it at a time. It’s simple and effective—great for most shared state scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using sync/atomic
&lt;/h3&gt;

&lt;p&gt;For basic numeric operations (like counters or flags), the sync/atomic package provides a faster, lock-free alternative.&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;import&lt;/span&gt; &lt;span class="s"&gt;"sync/atomic"&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&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;atomic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddInt64&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;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="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;atomic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddInt64&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;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="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;"Counter:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Atomic operations are lightweight and efficient—but they only work for specific use cases, like updating integers or booleans. You can't use them for complex updates or data structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Channels
&lt;/h3&gt;

&lt;p&gt;Channels are a Go-native way to synchronize access to data. Instead of locking, you "own" the value by passing it through a channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="c"&gt;// initialize&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;val&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;counter&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;val&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;val&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;counter&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// wait for goroutines&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;"Counter:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;counter&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 value lives inside the channel, and only one goroutine can access it at a time. It’s a safe and idiomatic way to coordinate shared state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which One Should You Use?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use Mutex: when you need simple locking for shared resources.&lt;/li&gt;
&lt;li&gt;Use Atomic: for fast, low-level operations on numbers.&lt;/li&gt;
&lt;li&gt;Use Channels: when goroutines need to communicate, not just protect data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Data races can quietly break your code in unpredictable ways. The good news? Go gives you simple tools to catch and fix them—like the -race flag, mutexes, channels, and atomic operations.&lt;/p&gt;

&lt;p&gt;Just remember: when goroutines share data, coordinate access. Pick the right tool for the job, and you’ll avoid a whole class of sneaky bugs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;"Don’t communicate by sharing memory; share memory by communicating."&lt;br&gt;
— Rob Pike&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;PRO TIP: Are you looking for an efficient way to create API documents for your projects?&lt;/p&gt;

&lt;p&gt;LiveAPI get all your backend API documented in one shot Try it out and share your feedback!&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%2Fukgim03pm0i8s2hw3c8y.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%2Fukgim03pm0i8s2hw3c8y.png" alt="Imagion" width="700" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Don't Let Your LLM Hallucinate—Check Out These Prompting Rules and Methods!</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Sun, 23 Feb 2025 16:12:46 +0000</pubDate>
      <link>https://forem.com/lincemathew/dont-let-your-llm-hallucinate-check-out-these-prompting-rules-and-methods-39jb</link>
      <guid>https://forem.com/lincemathew/dont-let-your-llm-hallucinate-check-out-these-prompting-rules-and-methods-39jb</guid>
      <description>&lt;p&gt;From the &lt;a href="https://fullstackdeeplearning.com/llm-bootcamp/" rel="noopener noreferrer"&gt;&lt;strong&gt;LLM Bootcamp lectures&lt;/strong&gt;&lt;/a&gt; by &lt;strong&gt;UC Berkeley PhD alumni&lt;/strong&gt;, I’ve learned key &lt;strong&gt;rules and methods&lt;/strong&gt; that improve prompts. This article covers techniques like &lt;strong&gt;Active Prompting, Meta Prompting, and Few-Shot Prompting&lt;/strong&gt; etc designed to make models think more systematically and produce better results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essential Rules for Writing Effective Prompts
&lt;/h2&gt;

&lt;p&gt;Here are a few important rules that can make prompts more effective. These techniques improve the accuracy and usefulness of responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Structured Text
&lt;/h3&gt;

&lt;p&gt;Language models perform better when given well-organized input. Just like humans find clear instructions easier to follow, models also work better with structured prompts.&lt;/p&gt;

&lt;p&gt;Example: Asking for a Python Function&lt;br&gt;
❌ Without Structure:&lt;br&gt;
"Write a Python function that checks if a number is prime."&lt;/p&gt;

&lt;p&gt;✅ With Structure (Pseudocode):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Define a function is_prime(n):
  If n is less than 2, return False
  For each number i from 2 to sqrt(n):
    If n is divisible by i, return False
  Return True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A structured prompt makes it easier for the model to understand and follow specific steps, reducing mistakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Break Down Complex Requests (Decomposition)
&lt;/h3&gt;

&lt;p&gt;When asking a model to complete a big task, it’s better to split it into smaller steps. This improves accuracy and keeps responses more focused.&lt;/p&gt;

&lt;p&gt;Example: Writing a Blog Post&lt;br&gt;
❌ All-in-One Prompt:&lt;br&gt;
"Write a blog post about climate change and include recent statistics."&lt;/p&gt;

&lt;p&gt;✅ Step-by-Step Approach:&lt;/p&gt;

&lt;p&gt;Gather facts: "List recent climate change statistics from 2023."&lt;br&gt;
Plan the content: "Create an outline for a climate change blog post."&lt;br&gt;
Write in parts: "Write an engaging introduction for a climate change blog post."&lt;br&gt;
Expand each section separately.&lt;br&gt;
Breaking down the task ensures each part is handled properly before moving to the next.&lt;/p&gt;

&lt;p&gt;✅ With Structure (Pseudocode):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Define a function is_prime(n):
  If n is less than 2, return False
  For each number i from 2 to sqrt(n):
    If n is divisible by i, return False
  Return True

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Guide the Model’s Reasoning (Chain of Thought)
&lt;/h3&gt;

&lt;p&gt;Instead of asking for a direct answer, guiding the model through logical steps leads to better responses.&lt;/p&gt;

&lt;p&gt;Example: Checking for a Prime Number&lt;br&gt;
❌ Simple Prompt:&lt;br&gt;
"Is 2,345 a prime number?"&lt;/p&gt;

&lt;p&gt;✅ Step-by-Step Prompt:&lt;br&gt;
"Let’s determine if 2,345 is a prime number by checking divisibility step by step."&lt;/p&gt;

&lt;p&gt;This approach encourages the model to explain its reasoning, making the response more reliable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Combine Multiple Responses (Ensembling)
&lt;/h3&gt;

&lt;p&gt;No model is perfect. Each has strengths and weaknesses, so combining multiple responses can lead to better accuracy.&lt;/p&gt;

&lt;p&gt;For example, instead of relying on a single model to summarize an article, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask two different models and compare results.&lt;/li&gt;
&lt;li&gt;Run the same model multiple times and merge the best answers.
This method helps filter out inconsistencies and improves response quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Different types of Prompting  Methods
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Active Prompting
&lt;/h3&gt;

&lt;p&gt;Active Prompting is a method that helps language models improve their reasoning by selecting the most useful examples for learning. Instead of relying on a fixed set of pre-written prompts, this approach identifies uncertain or ambiguous questions and refines them through human annotation.&lt;/p&gt;

&lt;h4&gt;
  
  
  How Active Prompting Works
&lt;/h4&gt;

&lt;p&gt;The process involves four key steps:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg93nwwsqkko2scdftwz4.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%2Fg93nwwsqkko2scdftwz4.png" alt="image" width="720" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uncertainty Estimation – The model answers a set of training questions multiple times (e.g., five attempts). If the answers vary significantly, the question is marked as uncertain.&lt;/li&gt;
&lt;li&gt;Selection – The most uncertain questions are chosen for human review.&lt;/li&gt;
&lt;li&gt;Annotation – Humans provide step-by-step reasoning for these selected questions.&lt;/li&gt;
&lt;li&gt;Inference – The newly annotated examples are added back into the system, improving the model’s accuracy for similar tasks.
#### Why Active Prompting Matters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Continue reading the complete article here: &lt;a href="https://journal.hexmos.com/dont-let-your-llm-hallucinate-check-out-these-prompting-rules-and-methods/" rel="noopener noreferrer"&gt;https://journal.hexmos.com/dont-let-your-llm-hallucinate-check-out-these-prompting-rules-and-methods/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>promptengineering</category>
      <category>ai</category>
    </item>
    <item>
      <title>Common API Design Mistakes and How to Avoid Them</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Tue, 31 Dec 2024 18:15:05 +0000</pubDate>
      <link>https://forem.com/lincemathew/common-api-design-mistakes-and-how-to-avoid-them-46e1</link>
      <guid>https://forem.com/lincemathew/common-api-design-mistakes-and-how-to-avoid-them-46e1</guid>
      <description>&lt;p&gt;Maintaining and designing scalable APIs is a tremendous task, especially once you have more than 100 APIs for your project. In the era of API as a Service, knowledge of API design is unavoidable.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss a few RESTful API design standards you can apply to your projects for building an ideal API ecosystem.&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%2Fsb7f0vztzf7des3iy084.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%2Fsb7f0vztzf7des3iy084.png" alt="Imagription" width="360" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Focus on Resources
&lt;/h3&gt;

&lt;p&gt;The fundamental purpose of APIs is to provide access to particular resources. An API resource represents a piece of data or functionality that the API provides access to. &lt;/p&gt;

&lt;p&gt;For example, in a CRM (Customer Relationship Management) application, typical resources include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contacts&lt;/li&gt;
&lt;li&gt;Leads&lt;/li&gt;
&lt;li&gt;Accounts&lt;/li&gt;
&lt;li&gt;Tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A resource can be in the form of a singleton (a single account) or a collection (a group of tasks).&lt;/p&gt;

&lt;p&gt;We can design an API in the format &lt;code&gt;GET /contacts&lt;/code&gt; to fetch a list of all contacts or &lt;code&gt;PUT /tasks/301&lt;/code&gt; to update a task's details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proper URL Naming
&lt;/h3&gt;

&lt;p&gt;Naming conventions are important for URLs. It is better to use nouns for RESTful URLs, as RESTful APIs are designed for collecting resources and communication, not for performing actions or operations.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Recommended Approach&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /contacts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /tasks/:id&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Less Preferred Approach&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /get-contacts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /get-task-by-id/:id&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Path Parameters
&lt;/h3&gt;

&lt;p&gt;Using path parameters provides a clear and structured way to identify resources and their relationships within the API.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /tasks/:id&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Avoid this&lt;br&gt;
&lt;/p&gt;

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

{
 id:1
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Maintain API hierarchy
&lt;/h3&gt;

&lt;p&gt;Maintaining a well-defined resource hierarchy helps define relationships between different resources in an API.&lt;/p&gt;

&lt;p&gt;In the case of CRM&lt;br&gt;
&lt;code&gt;GET /user/{userId}/task/{taskId}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, the API clearly fetches the task based on the task ID under a specific user.&lt;/p&gt;

&lt;h3&gt;
  
  
  API versioning
&lt;/h3&gt;

&lt;p&gt;APIs will get modified as the product grows. So, modifications to the API should not affect older users, older clients, or frontend code. That's when versioning comes in.&lt;/p&gt;

&lt;p&gt;Use API versioning when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renaming or changing any endpoint or property&lt;/li&gt;
&lt;li&gt;Parameter changes&lt;/li&gt;
&lt;li&gt;Modifying a data format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Versioning can be done by using URL Path Change or by using a Header.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;URL Path&lt;/em&gt;&lt;br&gt;
Version is defined in the path itself.&lt;br&gt;
Example: &lt;a href="https://example.com/api/v2/user" rel="noopener noreferrer"&gt;https://example.com/api/v2/user&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Header Versioning&lt;/em&gt;&lt;br&gt;
Version defined in the Header of the API&lt;br&gt;
Accept: version=1.0&lt;/p&gt;

&lt;p&gt;Maintaining and designing APIs is a never-ending challenge. It will differ for different products, use cases, and contexts. This article covers a few aspects that will help you to build better API ecosystems.&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%2Fyiwomxcfd7jrkcuhzuf4.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%2Fyiwomxcfd7jrkcuhzuf4.png" alt="Imiption" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My team and I are developing &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;, a super convenient API doc generation tool. Using &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;, you can create API documentation for any web project within minutes, with minimal effort. &lt;br&gt;
Also, once you connect, LiveAPI will keep your API documentation up to date based on code changes. &lt;/p&gt;

&lt;p&gt;Try LiveAPI and share your valuable feedback. Keep connected for more tech tips and articles.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>api</category>
    </item>
    <item>
      <title>Learn Golang in 2025, You Won't Regret It</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Sun, 29 Dec 2024 18:34:57 +0000</pubDate>
      <link>https://forem.com/lincemathew/learn-golang-in-2025-you-wont-regret-it-531f</link>
      <guid>https://forem.com/lincemathew/learn-golang-in-2025-you-wont-regret-it-531f</guid>
      <description>&lt;p&gt;As I explained in previous articles, we are working on building &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;, a super-convenient auto-API doc generation tool. LiveAPI's backend is in Golang, and I'm discovering the unique and cool features of Golang.&lt;/p&gt;

&lt;p&gt;For those who don't know, &lt;a href="https://github.com/golang/go" rel="noopener noreferrer"&gt;Golang (Go)&lt;/a&gt; is a programming language designed at Google in 2009. It is syntactically similar to C.&lt;/p&gt;

&lt;p&gt;Before working on Golang projects, I primarily used Node.js and Python web frameworks. For a beginner switching to Golang from another domain, it can be a little difficult initially, but once you practice and gain expertise, you won't leave.&lt;/p&gt;

&lt;p&gt;My first Golang project was to convert a Python CLI tool, &lt;a href="https://github.com/HexmosTech/glee" rel="noopener noreferrer"&gt;Glee&lt;/a&gt;, to Golang. &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%2F2qy4qjgricsi7xogx1r1.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%2F2qy4qjgricsi7xogx1r1.png" alt="Imagcription" width="220" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We found Python to be slower and maintaining a single compiled CLI binary to be very difficult, the binary sometimes not compatible with Mac OS. These and other issues forced us to switch to Golang. &lt;a href="https://www.reddit.com/r/golang/comments/1b0bao1/my_experience_with_go_as_a_python_developer/?utm_source=share&amp;amp;utm_medium=web3x&amp;amp;utm_name=web3xcss&amp;amp;utm_term=1&amp;amp;utm_content=share_button" rel="noopener noreferrer"&gt;Here is a Reddit post on the story&lt;/a&gt; and the issues behind the switch.&lt;/p&gt;

&lt;p&gt;In this article, I will explain the unique features in Golang that attracted me to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Goroutines - Lightweight Concurrency&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;func main() {
    go sayHello("World") // runs concurrently
    time.Sleep(1 * time.Second) 
}

func sayHello(name string) {
    fmt.Printf("Hello, %s!\n", name)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of goroutines like tiny workers that can do tasks independently. They're much lighter than traditional threads - you can create thousands of them without a performance hit.&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%2Fzouv8kac79pfv4at7lnc.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%2Fzouv8kac79pfv4at7lnc.png" alt="Imaription" width="300" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Channels - Built-in Communication&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;func main() {
    messages := make(chan string)
    go func() { messages &amp;lt;- "ping" }()
    msg := &amp;lt;-messages
    fmt.Println(msg)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Channels are like pipes that let goroutines communicate safely. Imagine two people passing notes through a tube - one writes and puts it in, the other takes it out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Defer - Cleanup Made Simple&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;func readFile() {
    file, err := os.Open("test.txt")
    defer file.Close() // Will run when function exits 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Defer is like setting a reminder for cleanup tasks. It's similar to writing a post-it note saying "don't forget to close the file" right when you open it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Interface Implementation - Implicit Contracts&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;type Writer interface {
    Write([]byte) (int, error)
}

type ConsoleWriter struct{}

func (cw ConsoleWriter) Write(data []byte) (int, error) {
    return fmt.Println(string(data))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go's interfaces are satisfied implicitly - if a type has the right methods, it automatically implements the interface. It's like joining a club: you don't need to formally declare membership; if you can do what the club requires, you're automatically in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Multiple Return Values - Native Error Handling&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;func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("cannot divide by zero")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Result:", result)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiple return values make error handling natural and explicit in Go. It's like getting both a package and a receipt when shopping - you can check if everything is okay before proceeding. This pattern encourages developers to handle errors properly.&lt;/p&gt;

&lt;p&gt;These are just a few features I like in Go. There are also others, like single executable binaries, faster performance, type inference, built-in testing support, and cross-compilation.&lt;/p&gt;

&lt;p&gt;If you're making resolutions for 2025, add Golang to your list. You won't regret it. Thanks for reading! If you want to learn Golang by contributing to an open-source project, check out &lt;a href="https://github.com/HexmosTech/glee" rel="noopener noreferrer"&gt;glee&lt;/a&gt; and &lt;a href="https://github.com/HexmosTech/Lama2" rel="noopener noreferrer"&gt;Lama2&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>go</category>
    </item>
    <item>
      <title>What is Mutex and How to Use it in Golang?</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Sat, 28 Dec 2024 20:07:45 +0000</pubDate>
      <link>https://forem.com/lincemathew/what-is-mutex-and-how-to-use-it-in-golang-1m1i</link>
      <guid>https://forem.com/lincemathew/what-is-mutex-and-how-to-use-it-in-golang-1m1i</guid>
      <description>&lt;p&gt;During the development of &lt;a href="https://liveapi.hexmos.com/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;, an Auto API documentation generation tool, I needed to implement a robust queue mechanism that scaled based on the number of server machine cores. This was crucial to prevent excessive resource usage (memory and CPU) that could lead to resource starvation, crashes, and a poor user experience.&lt;/p&gt;

&lt;p&gt;In this article, I'll explain how I utilized mutexes in Golang to address this challenge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a Mutex?&lt;/strong&gt;&lt;br&gt;
In concurrent programming, a Mutex (Mutual Exclusion) is a locking mechanism that prevents race conditions by ensuring only one goroutine can access a shared resource at a time.  It's akin to a key to a room – only one person can hold the key and enter at once.&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%2Fvd11vq7kfvmdgc2g551z.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%2Fvd11vq7kfvmdgc2g551z.png" alt="Imagiption" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mutex Usage in Golang&lt;/strong&gt;&lt;br&gt;
Let's illustrate how a Mutex can manage concurrent job execution:&lt;br&gt;
&lt;a href="https://pkg.go.dev/sync" rel="noopener noreferrer"&gt;Go's sync package &lt;/a&gt; provides several primitives for synchronization, with Mutex being one of the most commonly used tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var (
    maxConcurrentJobs int
    activeJobs        int
    jobMutex          sync.Mutex
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, the &lt;code&gt;activeJobs&lt;/code&gt; variable tracks the number of currently running jobs. Since multiple goroutines might attempt to modify this variable concurrently, leading to race conditions, we use a Mutex to synchronize access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Check if we can process more jobs
jobMutex.Lock()
if activeJobs &amp;gt;= maxConcurrentJobs {
    jobMutex.Unlock()
    // Wait before checking again
    time.Sleep(time.Second)
    continue
}
jobMutex.Unlock()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How a Mutex Works&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Locking&lt;/em&gt;: The &lt;code&gt;Lock()&lt;/code&gt; method acquires exclusive access to the critical section.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Unlocking&lt;/em&gt;: The &lt;code&gt;Unlock()&lt;/code&gt; method releases the lock.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Critical Section&lt;/em&gt;: The code between &lt;code&gt;Lock&lt;/code&gt; and &lt;code&gt;Unlock&lt;/code&gt; where the **shared resource is accessed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types of Mutexes in Golang&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;sync.Mutex&lt;/em&gt;: This is the basic mutual exclusion lock in Go. It allows only one goroutine to access the critical section at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type SafeCounter struct {
    mu    sync.Mutex
    count int
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;sync.RWMutex&lt;/em&gt;: This is a reader/writer mutex that allows multiple readers to access the shared resource simultaneously, but only one writer at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var rwMutex sync.RWMutex
// Reader methods
rwMutex.RLock()   // Lock for reading
rwMutex.RUnlock() // Unlock for reading

// Writer methods
rwMutex.Lock()    // Lock for writing
rwMutex.Unlock()  // Unlock for writing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mutexes are essential tools for managing shared resources in concurrent Go programs. They prevent race conditions and ensure data integrity by controlling access to critical sections of code.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>go</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Working on Redis streams? Don't forget these commands.</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Sat, 28 Dec 2024 01:31:13 +0000</pubDate>
      <link>https://forem.com/lincemathew/working-on-redis-streams-dont-forget-these-commands-5dlp</link>
      <guid>https://forem.com/lincemathew/working-on-redis-streams-dont-forget-these-commands-5dlp</guid>
      <description>&lt;p&gt;I’ve been learning and implementing Redis streams for the past few days to set up a real-time communication system and queue management for our product &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;, an auto API doc generation tool.&lt;/p&gt;

&lt;p&gt;In this article, let us discuss a few Redis Stream commands that you need to be aware of while building efficient solutions using Redis Streams.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;XADD: This command helps to add new entries to a stream. 
Example: &lt;code&gt;XADD mystream * sensor-id 1234 temperature 19.8 humidity 43.5&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command adds a new entry to the stream 'mystream'. The * tells Redis to auto-generate the entry ID. Each entry contains multiple field-value pairs (sensor-id, temperature, humidity).&lt;/p&gt;

&lt;p&gt;2.XREAD: This command reads entries from one or more streams. &lt;br&gt;
Example: &lt;code&gt;XREAD COUNT 2 STREAMS mystream 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This reads 2 entries from 'mystream' starting from the beginning (ID 0).&lt;/p&gt;

&lt;p&gt;3.XRANGE: This command returns entries within a specific ID range. &lt;br&gt;
Example: &lt;code&gt;XRANGE mystream 1641293000000-0 1641293060000-0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command is used to get historical data within a specific range.&lt;/p&gt;

&lt;p&gt;4.XGROUP CREATE: Creates a consumer group for stream processing. &lt;br&gt;
Example: &lt;code&gt;XGROUP CREATE mystream mygroup $&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Creates a consumer group named 'mygroup' for 'mystream'. The $ means the group will only read new messages (from the last ID).&lt;/p&gt;

&lt;p&gt;5.XREADGROUP: Reads from a stream as part of a consumer group. &lt;br&gt;
Example: &lt;code&gt;XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream &amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This reads one unread message from 'mystream' as consumer1 in mygroup. The &amp;gt; means "give me new messages that haven’t been delivered to other consumers".&lt;/p&gt;

&lt;p&gt;6.XCLAIM: Used to transfer ownership of pending messages. &lt;br&gt;
Example: &lt;code&gt;XCLAIM mystream mygroup consumer2 30000 1692312456878-0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will transfer ownership from one consumer to another within the same consumer group. This is particularly useful in handling failed consumers or rebalancing workloads. XCLAIM ensures no messages are lost if a consumer fails, enables work redistribution for better load balancing, and provides message recovery mechanisms.&lt;/p&gt;

&lt;p&gt;I hope these few commands help to give you an idea about Redis streams and their commands. Share your valuable feedback.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>redis</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I Created API Docs for 5 Open-source Projects Within 10 Minutes</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Wed, 25 Dec 2024 11:40:04 +0000</pubDate>
      <link>https://forem.com/lincemathew/i-created-api-docs-for-5-open-source-projects-within-10-minutes-4fg5</link>
      <guid>https://forem.com/lincemathew/i-created-api-docs-for-5-open-source-projects-within-10-minutes-4fg5</guid>
      <description>&lt;p&gt;Creating and maintaining API documentation for any project is a tremendous task that eats up most of your time. However, we can't ignore this step in web development engineering because API docs play a significant role in collaboration, decision-making, and guidance.&lt;/p&gt;

&lt;p&gt;For the last few months, my team and I have been working on developing &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;, a super convenient tool for creating API Docs with the help of AI. Existing documentation tools, for example, &lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;Swagger&lt;/a&gt;, take time and effort from developers to set up and maintain. We saw an opportunity here and developed an easy doc generation tool that works within a few clicks.&lt;/p&gt;

&lt;p&gt;Here, I will explain how I created API Docs using &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, sign up for &lt;a href="https://liveapi.hexmos.com/" rel="noopener noreferrer"&gt;LiveAPI here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&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%2F465l4ftf9g50yksx6coe.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%2F465l4ftf9g50yksx6coe.png" alt="Imagption" width="678" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once logged in, find and select the "Create API Docs" option.&lt;/li&gt;
&lt;/ol&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%2Fp91w42e3lhkvwev5kz5n.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%2Fp91w42e3lhkvwev5kz5n.png" alt="Imaiption" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Paste the GitHub/GitLab URL of the open-source or your personal project.&lt;/li&gt;
&lt;/ol&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%2F23293btm5xj0hv4mvjq0.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%2F23293btm5xj0hv4mvjq0.png" alt="Imagption" width="800" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the "Create Docs" button and allow a few minutes for the process to complete.&lt;/li&gt;
&lt;/ol&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%2F0qcu4cqzlz81b40zfyec.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%2F0qcu4cqzlz81b40zfyec.png" alt="Imaption" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once finished, the documentation will be hosted on LiveAPI, and you can access the link immediately.&lt;/li&gt;
&lt;/ol&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%2F9dy6n5rmjeh2x53nobj5.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%2F9dy6n5rmjeh2x53nobj5.png" alt="Imacription" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using this method, I created API docs for 5 open-source web projects within 10 minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/mongo-express/mongo-express" rel="noopener noreferrer"&gt;Mongo-express&lt;/a&gt;: A web-based MongoDB admin interface written with Node.js, Express, and Bootstrap 5&lt;/li&gt;
&lt;/ol&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%2Fgy7vg7w8m2las1rh0s1o.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%2Fgy7vg7w8m2las1rh0s1o.png" alt="Imagiption" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/inventree/InvenTree" rel="noopener noreferrer"&gt;InvenTree&lt;/a&gt;: An open-source inventory management system that provides powerful low-level stock control and part tracking.&lt;/li&gt;
&lt;/ol&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%2F48308u45c7u7c6p5zsiz.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%2F48308u45c7u7c6p5zsiz.png" alt="Imascription" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/freescout-help-desk/freescout" rel="noopener noreferrer"&gt;Freescout&lt;/a&gt;: FreeScout is the super lightweight and powerful free open source help desk and shared inbox built with PHP (Laravel framework).&lt;/li&gt;
&lt;/ol&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%2Fc1trlhev1bivzn9faoyp.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%2Fc1trlhev1bivzn9faoyp.png" alt="Imacription" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/BookStackApp/BookStack" rel="noopener noreferrer"&gt;BookStack&lt;/a&gt;: A platform for storing and organising information and documentation. &lt;/li&gt;
&lt;/ol&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%2Fadh7xkv31ocndqg0qc7u.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%2Fadh7xkv31ocndqg0qc7u.png" alt="Imription" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/raeperd/realworld-springboot-java" rel="noopener noreferrer"&gt;realworld-springboot-java&lt;/a&gt;: ReadWorld.io backend project using spring boot java using spring-security, spring-data-jpa&lt;/li&gt;
&lt;/ol&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%2Fqz2xteqhm8z9lspgnwad.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%2Fqz2xteqhm8z9lspgnwad.png" alt="Imaiption" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try &lt;a href="https://liveapi.hexmos.com/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt; today to create API docs for your personal or open-source projects in minutes.&lt;/p&gt;

&lt;p&gt;Want to learn more about LiveAPI's features? Check out our landing page here and find other blogs &lt;a href="https://dev.to/lincemathew"&gt;in my bio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow me for more exciting product news and tips!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>liveapi</category>
      <category>ai</category>
    </item>
    <item>
      <title>Redis Pub/Sub vs. Redis Streams: Choosing the Right Solution</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Mon, 23 Dec 2024 19:40:33 +0000</pubDate>
      <link>https://forem.com/lincemathew/redis-pubsub-vs-redis-streams-choosing-the-right-solution-2oei</link>
      <guid>https://forem.com/lincemathew/redis-pubsub-vs-redis-streams-choosing-the-right-solution-2oei</guid>
      <description>&lt;p&gt;While working on building a &lt;a href="https://dev.to/lincemathew/is-this-a-good-way-to-reduce-operational-costs-4ig2"&gt;Go binary tool ("Runner")&lt;/a&gt; for our product &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt; (the super convenient API doc generation tool), we needed to establish communication between LiveAPI's backend and Runner. We initially tried the &lt;a href="https://redis.io/docs/latest/develop/interact/pubsub/" rel="noopener noreferrer"&gt;Redis pub/sub &lt;/a&gt; mechanism but later realized it was insufficient for our use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problems with Redis Pub/Sub&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Redis Pub/Sub follows a traditional publish-subscribe model: Publishers send messages to channels, and subscribers receive messages from the channels they are subscribed to.&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%2Faoqmvrrcevuwaj9r6zs1.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%2Faoqmvrrcevuwaj9r6zs1.png" alt="pub/sub" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This presented several problems for LiveAPI:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Duplicate Operations and Wasted Resources&lt;/em&gt;: If a user ran the same Runner on multiple devices, the subscription behavior of pub/sub would cause the same operations to run on multiple devices, creating duplication and wasting resources.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Memory and Data Loss&lt;/em&gt;: Pub/sub doesn't retain or persist messages, so if the server crashed or a job failed due to a panic, there was no way to restart the operations.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lack of Acknowledgement&lt;/em&gt;: The LiveAPI backend had no indication that a job request from the consumer had reached the subscriber.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redis Streams as the Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Redis Streams provide a more robust and feature-rich messaging system. They are essentially append-only logs where producers add messages, and consumers read them.&lt;/p&gt;

&lt;p&gt;Redis Streams addresses the issues we encountered with Pub/Sub:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Avoids Duplicate Operations&lt;/em&gt;: Even if the same Runner is running on multiple devices, only one instance can read and acknowledge a message, preventing the duplicate operations that occurred with pub/sub.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Message Persistence&lt;/em&gt;: Redis Streams persist messages. If the server crashes, operations can be restarted with the same message.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Guaranteed Delivery and Acknowledgement&lt;/em&gt;: Redis Streams provides message acknowledgement, assuring the LiveAPI backend that job requests reach the intended subscriber.&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%2F779x8145zjf99e7drynr.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%2F779x8145zjf99e7drynr.png" alt="stream" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand Your Usecase&lt;/strong&gt;&lt;br&gt;
Redis Streams was selected as a solution for LiveAPI due to its message persistence, guaranteed delivery, message acknowledgement, and ability to prevent duplicate operations. &lt;/p&gt;

&lt;p&gt;While Pub/Sub is a simpler solution and better suited for real-time messaging, Streams offers more features and guarantees, making it ideal for use cases where data durability and reliability are critical.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>liveapi</category>
    </item>
    <item>
      <title>Never Give Up on Learning a New Web Framework. This trick will solve a significant part of the problem.</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Wed, 18 Dec 2024 05:50:28 +0000</pubDate>
      <link>https://forem.com/lincemathew/never-give-up-on-learning-a-new-web-framework-this-trick-will-solve-a-significant-part-of-the-54o8</link>
      <guid>https://forem.com/lincemathew/never-give-up-on-learning-a-new-web-framework-this-trick-will-solve-a-significant-part-of-the-54o8</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/lincemathew" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F1138237%2F84b2cb1c-8fe3-4f02-bbea-4edd8de7c7b7.jpeg" alt="lincemathew"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/lincemathew/simple-trick-to-create-api-docs-for-any-open-source-web-projects-iil" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Simple Trick to Create API Docs for any Open-source Web Projects&lt;/h2&gt;
      &lt;h3&gt;LinceMathew ・ Dec 18 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ai&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>learning</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Simple Trick to Create API Docs for any Open-source Web Projects</title>
      <dc:creator>LinceMathew</dc:creator>
      <pubDate>Wed, 18 Dec 2024 05:28:51 +0000</pubDate>
      <link>https://forem.com/lincemathew/simple-trick-to-create-api-docs-for-any-open-source-web-projects-iil</link>
      <guid>https://forem.com/lincemathew/simple-trick-to-create-api-docs-for-any-open-source-web-projects-iil</guid>
      <description>&lt;p&gt;When I started learning backend frameworks like Express.js, Spring Boot, and Django, one of my go-to activities was to explore GitHub.&lt;/p&gt;

&lt;p&gt;I'd find similar projects or open-source tools built on a specific framework and examine their file structures, API practices, and code. This approach significantly helped me understand how to code framework backend servers effectively.&lt;/p&gt;

&lt;p&gt;Similarly, many developers clone open-source web project repositories to learn a new framework, study folder structures, read source code, discover best practices, or use the project as a template.&lt;/p&gt;

&lt;p&gt;One common challenge with open-source projects is the lack of comprehensive API documentation. In this article, we'll explore how to effortlessly create API docs for any open-source web backend project in just a few clicks using &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt; is a super-convenient auto-API doc generation tool that can create API documentation for any open-source web project within minutes. Let's illustrate its use with an example.&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%2Frtrax9lzsqfkpy5hwa9z.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%2Frtrax9lzsqfkpy5hwa9z.png" alt="demo" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider the project &lt;a href="https://github.com/spring-projects/spring-petclinic" rel="noopener noreferrer"&gt;spring-petclinic&lt;/a&gt;, which has 7.8 stars on GitHub. Spring Petclinic is a Spring Boot application built using Maven or Gradle.  Currently, it lacks API documentation, so let's create one using LiveAPI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Guide to Creating API Docs
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Log In and Navigate
&lt;/h4&gt;

&lt;p&gt;Start by logging in to LiveAPI. &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%2Flhl0rbx77m0v7t6szn3a.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%2Flhl0rbx77m0v7t6szn3a.png" alt="logging in to" width="678" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once logged in, find and select the "Create API Docs" option.&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%2Fwrow9kykvfd0d03l0c2z.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%2Fwrow9kykvfd0d03l0c2z.png" alt="select the" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Paste GitHub/Gitlab URL
&lt;/h4&gt;

&lt;p&gt;Locate the GitHub/GitLab URL of your desired open-source project. Copy this URL and paste it into the provided input box. This will enable LiveAPI to access and work with the project's repository.&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%2Fz4wagccpnvmne9a7kc89.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%2Fz4wagccpnvmne9a7kc89.png" alt="Paste GitHub/Gitlab URL" width="800" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Create API Docs
&lt;/h4&gt;

&lt;p&gt;Click the "Create Docs" button and allow a few minutes for the process to complete.&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%2Fykdl0ut0cud433a4akbh.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%2Fykdl0ut0cud433a4akbh.png" alt="Create API Docs" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4. API Docs Ready
&lt;/h4&gt;

&lt;p&gt;LiveAPI will generate the API documentation for your project.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facz3cww4bgkskyyjvq9r.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%2Facz3cww4bgkskyyjvq9r.png" alt="LiveAPI will generate" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once finished, the documentation will be hosted on LiveAPI and you can access the link immediately.&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%2Fuoxn3tvio1lemjfu1w5r.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%2Fuoxn3tvio1lemjfu1w5r.png" alt="liveapi" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try this technique in &lt;a href="https://hexmos.com/liveapi/" rel="noopener noreferrer"&gt;LiveAPI&lt;/a&gt; and share the valuable feedback. happy coding&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
