<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Claudiu Nicola</title>
    <description>The latest articles on DEV Community by Claudiu Nicola (@clanic).</description>
    <link>https://dev.to/clanic</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%2F98248%2Fd9162dff-9b50-4ba6-8038-f3582e8b730f.jpg</url>
      <title>DEV Community: Claudiu Nicola</title>
      <link>https://dev.to/clanic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/clanic"/>
    <language>en</language>
    <item>
      <title>How to Use Private Go Modules with golangci-lint in GitHub Actions.</title>
      <dc:creator>Claudiu Nicola</dc:creator>
      <pubDate>Fri, 05 Jan 2024 15:54:07 +0000</pubDate>
      <link>https://dev.to/clanic/using-private-go-modules-with-golangci-lint-in-github-actions-288j</link>
      <guid>https://dev.to/clanic/using-private-go-modules-with-golangci-lint-in-github-actions-288j</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;We're at a point in the software development evolution when everybody recognizes the importance of &lt;em&gt;Continuous Integration (CI)&lt;/em&gt; in the &lt;em&gt;Software Development Life Cycle&lt;/em&gt; - or at least I hope. To be honest, I can't remember a project I've worked on that didn't have at least a basic CI pipeline in place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://golangci-lint.run/" rel="noopener noreferrer"&gt;&lt;strong&gt;golangci-lint&lt;/strong&gt;&lt;/a&gt; is an amazing open-source tool for CI in Go projects. Basically, it's an aggregator and a Go linters runner that makes life easier for developers. It includes all the well-known liners by default but also provides an easy way to integrate new ones.  &lt;/p&gt;

&lt;p&gt;============&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;In the following, we will go through the steps required for running &lt;strong&gt;golangci-lint&lt;/strong&gt; via &lt;strong&gt;GitHub Actions&lt;/strong&gt; for projects with private modules.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Setup personal access tokens in GitHub
&lt;/h4&gt;

&lt;p&gt;That can be done in both, personal accounts and organizations - depending on where the code is.&lt;/p&gt;

&lt;p&gt;You have to go to &lt;strong&gt;Settings -&amp;gt; Developer Settings&lt;/strong&gt; and click on &lt;strong&gt;Generate new token&lt;/strong&gt; button&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%2F6njj4orcesm5its6f7ok.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%2F6njj4orcesm5its6f7ok.png" alt="Developer settings" width="800" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the page opened you can choose between a personal or an organisation account. Here depends on your use case. Is it the project inside your account or inside of an organization account?&lt;/p&gt;

&lt;p&gt;Select the repository/repositories or even all the repositories (again, depending on your use case)&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%2Fywfcpm0srlms5wm0m5yg.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%2Fywfcpm0srlms5wm0m5yg.png" alt="Repositories" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and grant &lt;strong&gt;Read-only&lt;/strong&gt; access for &lt;strong&gt;Actions&lt;/strong&gt;. &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%2Fa7k8hc9flaz4de9n3q1s.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%2Fa7k8hc9flaz4de9n3q1s.png" alt="Grant access" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The access token will be shown. Copy it and keep it somewhere for the next step.&lt;/p&gt;

&lt;p&gt;Now, let's go back to the repository where the GH Action should run. Go to &lt;strong&gt;Settings -&amp;gt; Security -&amp;gt; Secrets and variables&lt;/strong&gt;&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%2Fa4vwbz2kvk2xa1pckre2.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%2Fa4vwbz2kvk2xa1pckre2.png" alt="Secrets and variables" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;click on &lt;strong&gt;New repository secret&lt;/strong&gt;, fill in the secret name, and paste the access token from the previous step&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%2Ftsdf8gg8t7o71hmh4sza.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%2Ftsdf8gg8t7o71hmh4sza.png" alt="Repository secret" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Setup GitHub Actions workflow
&lt;/h4&gt;
&lt;h5&gt;
  
  
  2.1. Add golangci-lint.yml to your workflows
&lt;/h5&gt;

&lt;p&gt;If it is not already exists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# source: https://github.com/golangci/golangci-lint-action?tab=readme-ov-file#how-to-use&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;golangci-lint&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="c1"&gt;# Optional: allow read access to pull request. Use with `only-new-issues` option.&lt;/span&gt;
  &lt;span class="c1"&gt;# pull-requests: read&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;golangci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lint&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1.21'&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;golangci-lint&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;golangci/golangci-lint-action@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# Require: The version of golangci-lint to use.&lt;/span&gt;
          &lt;span class="c1"&gt;# When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version.&lt;/span&gt;
          &lt;span class="c1"&gt;# When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit.&lt;/span&gt;
          &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1.54&lt;/span&gt;

          &lt;span class="c1"&gt;# Optional: working directory, useful for monorepos&lt;/span&gt;
          &lt;span class="c1"&gt;# working-directory: somedir&lt;/span&gt;

          &lt;span class="c1"&gt;# Optional: golangci-lint command line arguments.&lt;/span&gt;
          &lt;span class="c1"&gt;#&lt;/span&gt;
          &lt;span class="c1"&gt;# Note: By default, the `.golangci.yml` file should be at the root of the repository.&lt;/span&gt;
          &lt;span class="c1"&gt;# The location of the configuration file can be changed by using `--config=`&lt;/span&gt;
          &lt;span class="c1"&gt;# args: --timeout=30m --config=/my/path/.golangci.yml --issues-exit-code=0 &lt;/span&gt;

          &lt;span class="c1"&gt;# Optional: show only new issues if it's a pull request. The default value is `false`.&lt;/span&gt;
          &lt;span class="c1"&gt;# only-new-issues: true&lt;/span&gt;

          &lt;span class="c1"&gt;# Optional: if set to true, then all caching functionality will be completely disabled,&lt;/span&gt;
          &lt;span class="c1"&gt;#           takes precedence over all other caching options.&lt;/span&gt;
          &lt;span class="c1"&gt;# skip-cache: true&lt;/span&gt;

          &lt;span class="c1"&gt;# Optional: if set to true, then the action won't cache or restore ~/go/pkg.&lt;/span&gt;
          &lt;span class="c1"&gt;# skip-pkg-cache: true&lt;/span&gt;

          &lt;span class="c1"&gt;# Optional: if set to true, then the action won't cache or restore ~/.cache/go-build.&lt;/span&gt;
          &lt;span class="c1"&gt;# skip-build-cache: true&lt;/span&gt;

          &lt;span class="c1"&gt;# Optional: The mode to install golangci-lint. It can be 'binary' or 'goinstall'.&lt;/span&gt;
          &lt;span class="c1"&gt;# install-mode: "goinstall"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  2.2. Add &lt;strong&gt;GOPRIVATE&lt;/strong&gt; and &lt;strong&gt;GH_ACCESS_TOKEN&lt;/strong&gt; environment variables.
&lt;/h5&gt;

&lt;p&gt;The first one is to let the workflow know the private dependencies and the second one is to specify the access token created above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;golangci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lint&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;+     GOPRIVATE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.com/claudiunicolaa&lt;/span&gt;
&lt;span class="na"&gt;+     GH_ACCESS_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_ACCESS_TOKEN }}&lt;/span&gt;
    &lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.21"&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;golangci-lint&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;golangci/golangci-lint-action@v3&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  2.3. Automatically include a GitHub access token in the URL when interacting with GitHub repositories
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;golangci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lint&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GOPRIVATE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.com/claudiunicolaa&lt;/span&gt;
      &lt;span class="na"&gt;GH_ACCESS_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_ACCESS_TOKEN }}&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.21"&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;+     - run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git config --global url.https://$GH_ACCESS_TOKEN@github.com/.insteadOf https://github.com/&lt;/span&gt;
      &lt;span class="s"&gt;- name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;golangci-lint&lt;/span&gt;
        &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;golangci/golangci-lint-action@v3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;============&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;In this article, we learned how to use golangci-lint in GitHub Actions for projects with private modules. We went through the steps required to set up personal access tokens in GitHub and then used them to create repository secrets. We also added the required environment variables and created a workflow to run golangci-lint via GitHub Actions. By following these steps, you can now use golangci-lint to automatically check your Go projects for common coding mistakes and ensure that your code is consistent and maintainable.&lt;/p&gt;

&lt;p&gt;Thank you for reading this article. I hope that the information provided here will help you use golangci-lint in GitHub Actions for your Go projects with private modules. &lt;/p&gt;

&lt;p&gt;All the examples can be found in &lt;a href="https://github.com/claudiunicolaa/project-a-go/tree/main" rel="noopener noreferrer"&gt;this repository&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Good luck with your software development journey!&lt;/p&gt;

</description>
      <category>go</category>
      <category>github</category>
      <category>ci</category>
      <category>lint</category>
    </item>
    <item>
      <title>NATS Message Deduplication in Go</title>
      <dc:creator>Claudiu Nicola</dc:creator>
      <pubDate>Sat, 29 Apr 2023 00:32:47 +0000</pubDate>
      <link>https://dev.to/clanic/effortless-nats-message-deduplication-in-go-2ohl</link>
      <guid>https://dev.to/clanic/effortless-nats-message-deduplication-in-go-2ohl</guid>
      <description>&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt; / TL;DR&lt;/p&gt;

&lt;p&gt;&lt;code&gt;natsdedup&lt;/code&gt; is a simple and efficient message deduplication solution for NATS-based applications, focusing on content-based deduplication.&lt;/p&gt;

&lt;p&gt;It offers easy integration, configurable deduplication TTL, and in-memory caching. &lt;/p&gt;

&lt;p&gt;Check out the GitHub repository to get started and contribute to its growth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt;: &lt;a href="https://github.com/claudiunicolaa/natsdedup" rel="noopener noreferrer"&gt;github.com/claudiunicolaa/natsdedup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;——&lt;/p&gt;

&lt;p&gt;Today, I would like to introduce you to &lt;code&gt;natsdedup&lt;/code&gt;, a lightweight package for deduplicating messages on NATS subjects. This package comes in handy for users who are not utilizing NATS JetStream and its &lt;a href="https://nats.io/blog/new-per-subject-discard-policy/" rel="noopener noreferrer"&gt;built-in deduplication feature&lt;/a&gt;.&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%2Fn9j2hi1hu60okvodp9vu.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%2Fn9j2hi1hu60okvodp9vu.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;natsdedup&lt;/code&gt; package aims to enhance the efficiency and reliability of your NATS-based applications by offering a simple yet effective message deduplication solution. It listens to messages on a specified input subject, deduplicates them using a configurable time-to-live (TTL) cache, and forwards unique messages to a specified output subject.&lt;/p&gt;

&lt;p&gt;An interesting aspect of &lt;code&gt;natsdedup&lt;/code&gt; is that it focuses on deduplicating messages based on their content rather than their ID headers, unlike the built-in deduplication capabilities in NATS JetStream. This makes &lt;code&gt;natsdedup&lt;/code&gt; a suitable alternative for scenarios where content-based deduplication is desired.&lt;/p&gt;




&lt;p&gt;Let's dive into some key features of the &lt;code&gt;natsdedup&lt;/code&gt; package:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy Integration&lt;/strong&gt;: &lt;code&gt;natsdedup&lt;/code&gt; is designed to be easily integrated into your existing NATS-based applications. Just create a new instance of the Deduplicator struct, configure it with the input and output subjects, and run the deduplication process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configurable Deduplication&lt;/strong&gt;: The package allows you to set a custom deduplication time-to-live (TTL) value, giving you control over how long messages should be considered for deduplication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;In-Memory Caching&lt;/strong&gt;: The current implementation uses an in-memory cache for temporarily storing messages and efficiently deduplicating them. This ensures low-latency processing and minimal overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concurrency Control&lt;/strong&gt;: The package employs concurrency control mechanisms like mutexes to ensure thread-safe access to the shared message cache.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Extensibility&lt;/strong&gt;: &lt;code&gt;natsdedup&lt;/code&gt; has been designed with extensibility in mind. As the project evolves, there are plans to explore and implement more advanced caching strategies, such as disk-based caching, distributed caching, and support for popular caching systems like Redis or Memcached.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To get started with &lt;code&gt;natsdedup&lt;/code&gt;, head over to the GitHub &lt;a href="https://github.com/claudiunicolaa/%20raw%20`natsdedup`%20endraw%20" rel="noopener noreferrer"&gt;repository&lt;/a&gt;, where you will find usage examples, and the source code. Contributions are welcome, whether it's adding new features, improving existing ones, or providing feedback to help make this package even better.&lt;/p&gt;

&lt;p&gt;In conclusion, &lt;code&gt;natsdedup&lt;/code&gt; is a valuable addition to the NATS ecosystem, providing a straightforward message deduplication solution for applications that do not rely on NATS JetStream. Give it a try and see how it can improve the performance and reliability of your NATS-based projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt;: &lt;a href="https://github.com/claudiunicolaa/natsdedup" rel="noopener noreferrer"&gt;github.com/claudiunicolaa/natsdedup&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AWS Lambda Go logging middleware example</title>
      <dc:creator>Claudiu Nicola</dc:creator>
      <pubDate>Fri, 26 Feb 2021 18:58:23 +0000</pubDate>
      <link>https://dev.to/clanic/learning-golang-middlewares-23g3</link>
      <guid>https://dev.to/clanic/learning-golang-middlewares-23g3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;For experienced programmers: A recap is always welcomed.&lt;/p&gt;

&lt;p&gt;For beginners: you will have a description of what are and how middlewares work in a Go web app. Don't forget, the comments section is open. Leave a comment if you need more explanations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;We will see what middlewares mean from a web application perspective.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What represents the middlewares in a web app?
&lt;/h2&gt;

&lt;p&gt;Middleware is a way for defining the separation of concerns in an application (distributed or not). Sometimes is called "the glue" or "plumbing" since it helps "glue" together different services and passes data between them &lt;a href="https://www.webopedia.com/definitions/middleware/" rel="noopener noreferrer"&gt;[1]&lt;/a&gt; &lt;a href="https://www.cleverism.com/what-is-middleware-and-how-does-it-work/" rel="noopener noreferrer"&gt;[2]&lt;/a&gt;. Web applications are used for executing a set of instructions before the request is handle by a controller. The instructions are usually to filter the requests (e.g. is this user allowed to access this page?), logging the request and the list can continue.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to implement a middleware in Golang?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Requirement: Implement a logging middleware for AWS Lambda.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Checkout this &lt;a href="https://github.com/claudiunicolaa/aws-lambda-go-middleware-example" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Inspired by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.questionable.services/article/guide-logging-middleware-go/" rel="noopener noreferrer"&gt;A Guide To Writing Logging Middleware in Go &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://justinas.org/writing-http-middleware-in-go" rel="noopener noreferrer"&gt;Writing HTTP Middleware in Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zachjohnsondev.com/posts/lambda-go-middleware/" rel="noopener noreferrer"&gt;Writing Go Middleware for AWS Lambda &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Moesif/moesif-aws-lambda-go" rel="noopener noreferrer"&gt;Moesif AWS Lambda Go GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>go</category>
      <category>middleware</category>
    </item>
  </channel>
</rss>
