<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Safigo</title><description>Safigo&apos;s personal space</description><link>https://safigo.dev/</link><language>en</language><atom:link href="https://safigo.dev/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Thu, 27 Aug 2026 02:17:00 GMT</lastBuildDate><item><title>Social networks for non-social posting in 2026</title><link>https://safigo.dev/posts/2026-08-26-social-networks/</link><guid isPermaLink="true">https://safigo.dev/posts/2026-08-26-social-networks/</guid><description>Post with more questions than answers about social networks in 2026</description><pubDate>Thu, 27 Aug 2026 02:17:00 GMT</pubDate><content:encoded>&lt;h2&gt;Table of contents&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;&lt;details&gt;&lt;summary&gt;Open Table of contents&lt;/summary&gt;&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-08-26-social-networks/#goal&quot;&gt;Goal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-08-26-social-networks/#social-networks-in-2026&quot;&gt;Social networks in 2026&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-08-26-social-networks/#not-options-for-me&quot;&gt;Not options for me&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-08-26-social-networks/#mastodon&quot;&gt;Mastodon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-08-26-social-networks/#bluesky&quot;&gt;Bluesky&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-08-26-social-networks/#updates&quot;&gt;Updates&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-08-26-social-networks/#update-2026-08-31&quot;&gt;Update 2026-08-31&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;/details&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Goal&lt;/h2&gt;
&lt;p&gt;I don’t like social networks, and I’ve never used them in my life.
However, I have some need to post my thoughts and contact with people.&lt;/p&gt;
&lt;p&gt;Since Software Development, and Cybersecurity, and databases are my the main interests, it limits the selection circle.&lt;/p&gt;
&lt;p&gt;I want to write some thoughts, speak with other people and avoid AI generated content, marketing, and clickbait.&lt;/p&gt;
&lt;h2&gt;Social networks in 2026&lt;/h2&gt;
&lt;p&gt;While the obvious choice would be X for developers, the amount of AI generated content, marketing, and clickbait is overwhelming.&lt;/p&gt;
&lt;p&gt;Also, I understand the idea of paying subscriptions, but not in a pay-to-win model.
You pay, and you get a better reach, identical to Pay-To-Win in games, that is not for me.&lt;/p&gt;
&lt;p&gt;Amount of advertisements is also overwhelming, I’d say it’s much more than I’d tolerate.&lt;/p&gt;
&lt;p&gt;Am I ready to pay?
Maybe.
But the price should be reasonable and with no pay-to-win model.&lt;/p&gt;
&lt;h3&gt;Not options for me&lt;/h3&gt;
&lt;p&gt;Instagram, Facebook, TikTok, Threads, and similar platforms are not for me.&lt;/p&gt;
&lt;p&gt;The reasons are mine, subjective, and personal:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I don’t want to have a doom-scrolling across unlimited short videos, memes, and AI generated content.&lt;/li&gt;
&lt;li&gt;Similar point for overwhelming amount of images&lt;/li&gt;
&lt;li&gt;I want to have some place where technical people communicate, ideally not “influencers” and “content creators”, but people who are interested in the same topics as I am.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Mastodon&lt;/h2&gt;
&lt;p&gt;I’ve tried Mastodon a couple of times, it’s really nice.
It gives reasonably good experience, but there are some catches.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fediverse is not ideally implemented
&lt;ul&gt;
&lt;li&gt;History of posts from other instances is not available, I need to go to another instance to see them&lt;/li&gt;
&lt;li&gt;To be visible on other instances, I need to follow them, and they need to follow me back&lt;/li&gt;
&lt;li&gt;Sometimes caching makes posts inconsistent between instances&lt;/li&gt;
&lt;li&gt;Instances may have different configurations that leads to different user experience, and inconsistent experience across instances&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Clients are much laggier that for other services, web interface is only reliable option&lt;/li&gt;
&lt;li&gt;Experience of reading posts is different between clients and web interface&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After experiencing significant amount of issues and limitations for searching the right instance,
it did not feel comfortable for me.&lt;/p&gt;
&lt;p&gt;And of the most interesting limitations I couldn’t explain, is that Mastodon claims to be a decentralized social network,
but I did not own my own profile. If I decide to switch to another instance, I will lose my ID.&lt;/p&gt;
&lt;p&gt;It means, I don’t choose a decentralized instance, I choose a centralized instance that is part of a decentralized network.&lt;/p&gt;
&lt;p&gt;It could be simply fixed by supporting DNS records for user profiles, and assigning an “email-like” ID to each user.
Users would have a chance to migrate between instances without losing their ID.&lt;/p&gt;
&lt;h2&gt;Bluesky&lt;/h2&gt;
&lt;p&gt;Bluesky looks promising, and an initial idea was nice, but the reaching part is tricky.
After X and Mastodon in feels silent, maybe not entirely, but not as warm as Mastodon.&lt;/p&gt;
&lt;p&gt;And tricky, not clear at first, Feeds feature and decentralization.&lt;/p&gt;
&lt;p&gt;Anyway, I chose to use Bluesky, and I will see how it goes.
I hope to see you there 👋&lt;/p&gt;
&lt;h2&gt;Updates&lt;/h2&gt;
&lt;h3&gt;Update 2026-08-31&lt;/h3&gt;
&lt;p&gt;I have tried to use BlueSky for a couple of days.
It was surprising how concentrated it was with politics and weirdly enough, screenshots from X.&lt;/p&gt;
&lt;p&gt;Since the most of the people use X, it looks like BlueSky contains reposts from X.&lt;/p&gt;
&lt;p&gt;I’ll try to use X in parallel with BlueSky, and give a chance to win only by one of them.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>social</category><category>social networks</category></item><item><title>UX and ML-Driven Functionality in Modern Music Streaming Services</title><link>https://safigo.dev/posts/2026-06-ux-ml-music-streaming/</link><guid isPermaLink="true">https://safigo.dev/posts/2026-06-ux-ml-music-streaming/</guid><description>Some observations on the current state of popular music streaming services and their user experience.</description><pubDate>Tue, 02 Jun 2026 03:15:08 GMT</pubDate><content:encoded>&lt;h2&gt;Table of contents&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;&lt;details&gt;&lt;summary&gt;Open Table of contents&lt;/summary&gt;&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#a-mental-shift&quot;&gt;A Mental Shift&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#addiction-to-youtube&quot;&gt;Addiction to YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#switching-to-music&quot;&gt;Switching to Music&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#choosing-a-streaming-service&quot;&gt;Choosing a Streaming Service&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#youtube-music&quot;&gt;YouTube Music&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#amazon-music&quot;&gt;Amazon Music&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#apple-music&quot;&gt;Apple Music&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#spotify&quot;&gt;Spotify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#closing-thoughts&quot;&gt;Closing Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;/details&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;A Mental Shift&lt;/h2&gt;
&lt;p&gt;I’ve never really been into social networks. It’s not that I was inherently against them from day one, it was more about my lack of personal involvement.&lt;/p&gt;
&lt;p&gt;I remember my the first social network, I used it primarily as a chat program. It was simply a place where we could send text messages because everyone around us was there. Sharing things publicly, &lt;em&gt;opinions, photos, jokes&lt;/em&gt;, just wasn’t my thing. Since I was never deeply affected by social networks, I remained largely untouched when they began impacting our social lives too heavily and the digital dangers became real.&lt;/p&gt;
&lt;h3&gt;Addiction to YouTube&lt;/h3&gt;
&lt;p&gt;However, one platform did manage to make me dependent, and even addicted: YouTube.&lt;/p&gt;
&lt;p&gt;When Apple shipped the Screen Time feature, it became clear that I was spending far too much time with YouTube active on my phone.
I was constantly either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Listening to videos in the background&lt;/li&gt;
&lt;li&gt;Watching videos actively&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It became a non-stop process. Whether it was cognitive overload or something else, I realized I could mindlessly scroll through YouTube for minutes without actually selecting a video to watch.&lt;/p&gt;
&lt;p&gt;When YouTube released the “Shorts” feature, it introduced a new problem. Now, I wasn’t just scrolling warching long videos, I was literally spending hours watching Shorts. That was the moment I truly understood how TikTok affects people. Lately, YouTube has become less interesting to me (mostly due to broken recommendations), but the underlying habit remains an issue.&lt;/p&gt;
&lt;h3&gt;Switching to Music&lt;/h3&gt;
&lt;p&gt;I’m not entirely sure how sound this decision is, but I thought I would try moving away from addictive videos and transition to music.&lt;/p&gt;
&lt;p&gt;Due to my “unusual” personality I had almost never listened to music in my life. That left me in a situation where I had almsot no preferences. It doesn’t mean I can’t distinguish what I like from what I don’t, it just means I don’t &lt;em&gt;know&lt;/em&gt; what exactly I’d like. I needed use “recommendations” to build my own list.&lt;/p&gt;
&lt;p&gt;It meant I need to choose a streaming service where I can feel comfortable.&lt;/p&gt;
&lt;h2&gt;Choosing a Streaming Service&lt;/h2&gt;
&lt;p&gt;it was obvious, I needed a service where I could choose a few initial songs and artists, and use it’s recommendations to build a library.&lt;/p&gt;
&lt;p&gt;In my mind, I had only one core requirement: I wanted a “magic playlist” that would combine my randomly shuffled &lt;strong&gt;saved music&lt;/strong&gt; (songs I enjoy and have liked/favorited) with a &lt;strong&gt;shuffled in recommendations&lt;/strong&gt;. To me, this felt like the best possible user experience to get started. At least during my the first few months.&lt;/p&gt;
&lt;h3&gt;YouTube Music&lt;/h3&gt;
&lt;p&gt;YouTube Music was the most obvious solution, and I almost liked it. However, I cannot understand who made the &lt;em&gt;genius&lt;/em&gt; decision to limit it “wearable” client to work ONLY with connected phone.&lt;/p&gt;
&lt;p&gt;When I ride a bike or go to the gym, I don’t want to bring my phone with me. I prefer to connect my smartwatch directly to my headphones and listen music completely without phone. It’s an incredibly comfortable setup.&lt;/p&gt;
&lt;p&gt;Because of this limitation, YouTube Music was removed from my list automatically, without any second chances.&lt;/p&gt;
&lt;h3&gt;Amazon Music&lt;/h3&gt;
&lt;p&gt;I don’t remember exactly why or how, but Amazon Music offered me a 3-month free trial right around this time. I couldn’t resist taking it for a try.&lt;/p&gt;
&lt;p&gt;Amazon Music works reasonably well on a smartwatch… almost. In general, it works, but it’s quality is similar across all Amazon’s applications: the UI feels unresponsive and laggy.&lt;/p&gt;
&lt;p&gt;While Amazon Music has made steps forward, it only works well, until it doesn’t. Sometimes, when skipping to the next track or going back to a previous one, the synchronization between album art, title, and audio breaks entirely. It can display the image from one track, the title from another, and play the audio from a third.&lt;/p&gt;
&lt;p&gt;The most frustrating part? When it break on my smartwatch during a ride.&lt;/p&gt;
&lt;h3&gt;Apple Music&lt;/h3&gt;
&lt;p&gt;Since I am deeply invested into Apple’s ecosystem, it made sense to try Apple Music, expecting a highly consistent experience. While for Linux, it provides a functional Web UI.&lt;/p&gt;
&lt;p&gt;But after spending some time with it, I realized their recommendation engine simply doesn’t work for me. I read all their playlists are “hand-picked.”, but those curated selections never quite aligned with my taste.&lt;/p&gt;
&lt;p&gt;Apple Music features a personalized station called “User’s Station,” but whenever I put it on, I wanted to skip every single song. The tracks felt completely disconnected from what I’d expect.&lt;/p&gt;
&lt;p&gt;Moreover, one interesting feature that frustrated me, I did not expect from Apple.. When I was playing music via the Web UI and tried to switch to my mobile phone, instead of seamlessly moving the active playback between devices, it showed me an error that I need a “Family” subscription to listen on multiple devices. I haven’t similar issues on other services.&lt;/p&gt;
&lt;h3&gt;Spotify&lt;/h3&gt;
&lt;p&gt;And here we are!&lt;/p&gt;
&lt;p&gt;Everyone recommends Spotify for its legendary recommendation algorithm. I expected this algorithmic magic to make me happy right from the start.&lt;/p&gt;
&lt;p&gt;To be fair, Spotify boasts the highest UI quality. It just works. From my perspective, there are only two streaming services consistently building top-tier user interfaces: &lt;strong&gt;Netflix&lt;/strong&gt; and &lt;strong&gt;Spotify&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Regardless, I started the app, completed an onboarding experience, and started listening. To my surprise, I couldn’t find an obvious &lt;strong&gt;“User’s Station”&lt;/strong&gt; equivalent on the home screen like Apple Music had.
It features many automated playlists, but all of them were standard &lt;em&gt;Artist and Similar&lt;/em&gt; radios.&lt;/p&gt;
&lt;p&gt;It wasn’t quite what I was hunting for.&lt;/p&gt;
&lt;p&gt;After many attempts and our lovely chat bots, who help us search in internet I’ve found a hidden feature: &lt;strong&gt;Smart Shuffle&lt;/strong&gt; inside the &lt;strong&gt;Liked Songs&lt;/strong&gt; playlist. This was exactly what I had been searching for.&lt;/p&gt;
&lt;p&gt;Over the last few days, I’ve quite enjoyed Spotify, and I plan to stick with it for now.&lt;/p&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;I understand that my specific use case might be an outlier, but it feels clear to me that &lt;strong&gt;Discovery&lt;/strong&gt; and &lt;strong&gt;Shuffled In&lt;/strong&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#user-content-fn-shuffled&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; playlists should be on the main screen.&lt;/p&gt;
&lt;p&gt;Do most people really listen to music by looking for recommendations based on an artist or a song?&lt;/p&gt;
&lt;p&gt;From a good UX, I’d expect those playlists on the main screen:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Discovery&lt;/strong&gt;: A dedicated space to find new suggestions based on the current intests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shuffled In&lt;/strong&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#user-content-fn-shuffled&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;: The hybrid mix of known favorites and new algorithmic suggestions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mood-Based Playlists&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time-and-Activity Categories&lt;/strong&gt; (e.g., morning focus, workout, evening wind-down)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’d love to hear from others on this. How disconnected are my UX expectations from an average streaming user?&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A dynamic playlist with a randomly shuffled mix of my &lt;strong&gt;liked/favorite&lt;/strong&gt; songs with randome suggestions of &lt;strong&gt;new, recommended tracks&lt;/strong&gt;. &lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#user-content-fnref-shuffled&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2026-06-ux-ml-music-streaming/#user-content-fnref-shuffled-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>music</category><category>ml</category><category>streaming</category></item><item><title>Phishing through referral links: A case study with DigitalOcean</title><link>https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/</link><guid isPermaLink="true">https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/</guid><description>A case study of phishing through referral links, specifically focusing on DigitalOcean</description><pubDate>Sun, 17 May 2026 05:58:32 GMT</pubDate><content:encoded>&lt;h2&gt;Table of contents&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;&lt;details&gt;&lt;summary&gt;Open Table of contents&lt;/summary&gt;&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#rise-of-phishing-through-official-emails&quot;&gt;Rise of phishing through “official” emails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#case-study-digitalocean-referral-links&quot;&gt;Case study: DigitalOcean referral links&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#reminder&quot;&gt;Reminder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#what-can-happen-if-you-engage&quot;&gt;What can happen if you engage&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#clicking-accept-invitation-link&quot;&gt;Clicking “Accept Invitation” link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#replying-to-the-email&quot;&gt;Replying to the email&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#calling-the-phone-number&quot;&gt;Calling the phone number&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-05-phishing-referral-digitalocean/#reporting-this-to-digitalocean&quot;&gt;Reporting this to DigitalOcean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;/details&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Rise of phishing through “official” emails&lt;/h2&gt;
&lt;p&gt;There used to be nice times when we received emails from &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;randomemail@gmail.com&lt;/code&gt; with an impersonation to some service or person.
It was simple to filter out those emails, but just looking at the sender’s email address.&lt;/p&gt;
&lt;p&gt;Not anymore. Recent years there was a switch to utilizing ways to send emails with custom text from an official service.&lt;/p&gt;
&lt;p&gt;The most popular example of emails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Referral links&lt;/li&gt;
&lt;li&gt;Invitation to a community/group&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since all of those emails put some sender’s information (sometimes with a custom text), that utilized to be used for phishing emails.&lt;/p&gt;
&lt;h2&gt;Case study: DigitalOcean referral links&lt;/h2&gt;
&lt;p&gt;Recently, I received an email from DigitalOcean containing a referral invitation. It looked like this:
&lt;img alt=&quot;Email from DigitalOcean with referral link&quot; width=&quot;2094&quot; height=&quot;1301&quot; src=&quot;https://safigo.dev/_astro/digitalocean-referral-email-phishing.BkWqYLXk_u0JIv.webp&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;Key parts of the email were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Subject&lt;/strong&gt;: &lt;em&gt;Join the ‘Your Bank account will be charged 499 USD_Call 656-556-2282 if unauthorized’ team on DigitalOcean&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sender’s name&lt;/strong&gt;: &lt;em&gt;DigitalOcean via Your Bank account will be charged 499 USD_Call 656-556-2282 if unauthorized&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Email address&lt;/strong&gt;: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;no-reply@referrals.digitalocean.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom text from body&lt;/strong&gt;: &lt;em&gt;Your bank/PayPal account will be charged $499.99 for your Norton-360 Deluxe subscription. Please call +1 (656) 556 - 2282 immediately if unauthorized; otherwise, the charge will process in 12 hours. Invoice ID: N7R47 (&lt;a href=&quot;mailto:arjunb.hamre.96@gmail.com&quot;&gt;arjunb.hamre.96@gmail.com&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though the email does not look consistent, by inviting to &lt;strong&gt;join a team&lt;/strong&gt;, and only CTA is to &lt;strong&gt;Accept Invitation&lt;/strong&gt;,
text about a significant charge and direct communication methods may confuse users and make them to call/write to the scammers.&lt;/p&gt;
&lt;h2&gt;Reminder&lt;/h2&gt;
&lt;p&gt;While we used to rely on “technical” indicators of phishing emails, such as the sender’s email address,
it is now equally important to inspect the content and intent of the message.&lt;/p&gt;
&lt;p&gt;Many companies provide anti-phishing training and checklists.
Use them regularly, and pause before acting on any urgent or emotional request.&lt;/p&gt;
&lt;h2&gt;What can happen if you engage&lt;/h2&gt;
&lt;p&gt;Let’s assume someone falls into the trap. What could happen next?&lt;/p&gt;
&lt;p&gt;At least three scenarios are likely.&lt;/p&gt;
&lt;h3&gt;Clicking “Accept Invitation” link&lt;/h3&gt;
&lt;p&gt;The link may lead to accepting an empty project.
This DigitalOcean org/project does not provide benefits, but it confirms the email is active and that you engage with messages.
This may lead to more phishing emails in the future.&lt;/p&gt;
&lt;p&gt;It may also expose additional account context that helps attackers research you using OSINT techniques,
making future phishing attempts more personalized.&lt;/p&gt;
&lt;p&gt;Also, they have a bond with you, since you are registered in DigitalOcean and the future emails will be more personalized,
which may increase the chances of falling for the scam.
More targeted attacks.&lt;/p&gt;
&lt;h3&gt;Replying to the email&lt;/h3&gt;
&lt;p&gt;Replying to the email will lead to a slow communication with scammers.
They won’t try to scam in the first message, but they will try to build trust, scare you, and make you to make required actions.&lt;/p&gt;
&lt;p&gt;Email is dangerous not only because scammers can request to pay something or steal data, but also
because it can become a channel for technical attacks (malicious attachments, credential-harvesting links, and similar payloads).&lt;/p&gt;
&lt;h3&gt;Calling the phone number&lt;/h3&gt;
&lt;p&gt;Calling is often the most dangerous step, because scammers can pressure you in real time.
During the call, it’s very hard to take a break and process the information.&lt;/p&gt;
&lt;p&gt;They want immediate action without giving you time to think or verify.
Typical scare tactics include fake charges, account lockouts, or threats about stolen personal information.&lt;/p&gt;
&lt;h2&gt;Reporting this to DigitalOcean&lt;/h2&gt;
&lt;p&gt;I tried to report this email to DigitalOcean, but they made it harder than it should be.&lt;/p&gt;
&lt;p&gt;It’s not as simple as forwarding the email to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;abuse@digitalocean.com&lt;/code&gt;, but you need to &lt;a href=&quot;https://www.digitalocean.com/company/contact/abuse&quot;&gt;fill out a form&lt;/a&gt; with various information about the email.
The form currently has no way to attach the original email, PDF, or screenshot.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>phishing</category><category>digitalocean</category></item><item><title>Windows after macOS</title><link>https://safigo.dev/posts/2026-03-windows-after-macos/</link><guid isPermaLink="true">https://safigo.dev/posts/2026-03-windows-after-macos/</guid><description>I have been shocked after seeing Windows, after 10 years of using macOS</description><pubDate>Fri, 20 Mar 2026 04:36:36 GMT</pubDate><content:encoded>&lt;h2&gt;Table of contents&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;&lt;details&gt;&lt;summary&gt;Open Table of contents&lt;/summary&gt;&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#my-desktop-os-journey&quot;&gt;My Desktop OS Journey&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#the-early-days&quot;&gt;The Early Days&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#the-floppy-disk-hack&quot;&gt;The Floppy Disk Hack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#moving-to-xp-and-programming&quot;&gt;Moving to XP and Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#the-shift-to-linux-and-macos&quot;&gt;The Shift to Linux and macOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#my-new-pc&quot;&gt;My New PC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#os-comparison&quot;&gt;OS Comparison&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#macos-the-ecosystem&quot;&gt;macOS: The Ecosystem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#windows-11-the-reality-check&quot;&gt;Windows 11: The Reality Check&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#1-setup-and-package-management&quot;&gt;1. Setup and Package Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#2-the-ad-experience&quot;&gt;2. The Ad Experience&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#3-missing-core-apps&quot;&gt;3. Missing Core Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#4-gaming-stability&quot;&gt;4. Gaming Stability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#5-wsl-windows-subsystem-for-linux&quot;&gt;5. WSL (Windows Subsystem for Linux)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#bottom-line&quot;&gt;Bottom Line&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;/details&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;My Desktop OS Journey&lt;/h2&gt;
&lt;h3&gt;The Early Days&lt;/h3&gt;
&lt;p&gt;I started my desktop OS journey with &lt;strong&gt;Windows 95&lt;/strong&gt;, when my father brought home an old laptop.
It wasn’t stable or performant enough to render cartoons using Flash, but it was the first device I could use.&lt;/p&gt;
&lt;p&gt;I was a kid, fascinated by the idea of a computer, and I wanted to learn how to use it.
I spent hours experimenting and reading about different software and capabilities of the OS.&lt;/p&gt;
&lt;h3&gt;The Floppy Disk Hack&lt;/h3&gt;
&lt;p&gt;At that time, we used floppy disks, and they could not fit a game on &lt;strong&gt;1.44 MB&lt;/strong&gt;.
As a kid, I had a “brilliant” idea to go to my friend’s house and copy &lt;strong&gt;shortcuts&lt;/strong&gt; (symlinks) from his computer.
It felt like a way to hack the system by copying all of his games onto a single floppy disk.&lt;/p&gt;
&lt;p&gt;It was a huge disappointment when it didn’t work, but that is where I started to learn &lt;em&gt;why&lt;/em&gt; and &lt;em&gt;what&lt;/em&gt; I could do instead.
Fortunately, there were books I could read to learn more about Windows 95 and related programs.&lt;/p&gt;
&lt;h3&gt;Moving to XP and Programming&lt;/h3&gt;
&lt;p&gt;After some time, I managed to convince my parents to pay a fortune for a new computer.
It was a tower PC with &lt;strong&gt;Windows XP&lt;/strong&gt;, and it was a huge step forward in performance and stability.
I was able to play games and try different programs available at that time.&lt;/p&gt;
&lt;p&gt;This was the PC where I started to learn programming. My first motivation was to automate an &lt;strong&gt;Ultima Online&lt;/strong&gt; client, a popular MMORPG.
My character could move by itself, chop wood, and train skills without me being there.&lt;/p&gt;
&lt;h3&gt;The Shift to Linux and macOS&lt;/h3&gt;
&lt;p&gt;Unfortunately, hardware kept moving forward, and my PC struggled with new Windows versions and games.
That’s when I first tried &lt;strong&gt;Linux&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I didn’t want to learn Linux. I just wanted to install it and use it like Windows. That didn’t go as planned.
After some trial and error, I found myself with &lt;strong&gt;Gentoo Linux&lt;/strong&gt; and a good understanding of how it worked.&lt;/p&gt;
&lt;p&gt;When I got my first job, I used Linux for work and kept Windows only for gaming.
Later, companies started providing MacBooks. After some initial conflicts (especially with the Magic Mouse), I switched to &lt;strong&gt;macOS&lt;/strong&gt; as my main OS and was really happy with it.&lt;/p&gt;
&lt;p&gt;For the last 10 years, I haven’t used Linux or Windows daily. I was locked into Apple’s ecosystem.
To be fair, it works great, except for gaming and my nostalgia for Linux.&lt;/p&gt;
&lt;h2&gt;My New PC&lt;/h2&gt;
&lt;p&gt;Recently, I decided to buy a new PC. A real tower PC, like the ones from the past.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It allows upgrades and lets you see what is inside.&lt;/li&gt;
&lt;li&gt;It doesn’t require battery optimizations or sleep mode management.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As expected, the device came with &lt;strong&gt;Windows 11&lt;/strong&gt;, and I thought I would use it as my main OS.
I remembered Microsoft doing a great job with &lt;strong&gt;WSL&lt;/strong&gt; and &lt;strong&gt;WSL2&lt;/strong&gt;.
I thought that after all these years, Windows would provide a better development experience than macOS.
Plus, &lt;strong&gt;gaming&lt;/strong&gt; is a huge bonus.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Oh man, I was so wrong.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What exactly shocked me? I’ll share that in a moment. But first, the Linux part.
I installed different Linux distributions and was surprised by how limited some package managers are (different PPAs, untrustworthy repositories).
After some hopes and warm memories of Gentoo, I settled on &lt;strong&gt;Arch Linux&lt;/strong&gt;, which is now the main OS on my new PC.&lt;/p&gt;
&lt;h2&gt;OS Comparison&lt;/h2&gt;
&lt;h3&gt;macOS: The Ecosystem&lt;/h3&gt;
&lt;p&gt;I was really happy with macOS. It was stable, fast, and had a great software ecosystem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Safari&lt;/strong&gt;: A good browser. It works, is energy efficient, and has almost no compatibility issues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Terminal&lt;/strong&gt;: Good enough. I recently moved to &lt;strong&gt;Ghostty&lt;/strong&gt; (a really good terminal emulator), but the default Terminal has all the required features.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Homebrew&lt;/strong&gt;: Works like a charm. It has all the packages I’ve ever needed. It is the package manager I’d expect in Linux (especially Ubuntu).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native Apps&lt;/strong&gt; (Mail, Calendar, Notes, Reminders, Maps, Photos, Music): These apps are amazing. They are minimalistic but work well. I rarely looked for replacements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Apple managed to build most apps that people need (outside of professional exceptions).
There is no need to pay for or download extras. Many users stay inside this default set and are happy.&lt;/p&gt;
&lt;h3&gt;Windows 11: The Reality Check&lt;/h3&gt;
&lt;p&gt;Windows? Windows is different.
I heard many negative things about Windows over the years, but people always complain, right?
However, from my experience:&lt;/p&gt;
&lt;h4&gt;1. Setup and Package Management&lt;/h4&gt;
&lt;p&gt;Windows loaded quite fast. I had an issue with the PIN code setup, but in general, the experience was okay.
Then I learned about &lt;strong&gt;winget&lt;/strong&gt;. I was really surprised—having a native package manager with many apps is a huge plus.&lt;/p&gt;
&lt;p&gt;But &lt;strong&gt;winget&lt;/strong&gt; was also the first disappointment.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some apps installed via winget did not work.&lt;/li&gt;
&lt;li&gt;I had to download installers from official websites and install them manually anyway.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. The Ad Experience&lt;/h4&gt;
&lt;p&gt;After installation, I saw many news widgets and unexpected pop-ups. It felt like some of them were promotions.
&lt;strong&gt;Who expects to see ads on their desktop OS?&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;3. Missing Core Apps&lt;/h4&gt;
&lt;p&gt;The next step was opening Calendar, Mail, or Notes.
I was surprised to see that real native programs are effectively missing.
They are there, but they feel like &lt;strong&gt;web views&lt;/strong&gt; or just stripped-down versions of Outlook with limited functionality unless you subscribe.&lt;/p&gt;
&lt;p&gt;Pre-installed &lt;strong&gt;Copilot&lt;/strong&gt; is forced as much as possible. And &lt;strong&gt;Edge&lt;/strong&gt;…
Edge is a decent browser, but it has too many “features” on top. I prefer a minimalistic browser.&lt;/p&gt;
&lt;h4&gt;4. Gaming Stability&lt;/h4&gt;
&lt;p&gt;Windows is the GOAT of gaming, right? At least I thought so.
In general, games work with fewer compatibility issues (after the initial shader compilation).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But why do games crash so often?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I installed &lt;strong&gt;Fallout&lt;/strong&gt; from Xbox (via the Game Pass subscription that came with the PC).
During the first hour, it crashed about 10 times.
I’m not sure why I was so motivated to keep playing, but is this how people play on PC?
Did I do something wrong? I don’t know, but the experience was unpleasant.&lt;/p&gt;
&lt;h4&gt;5. WSL (Windows Subsystem for Linux)&lt;/h4&gt;
&lt;p&gt;And last but not least: &lt;strong&gt;WSL&lt;/strong&gt;.
It’s the feature everyone praised for Linux integration.&lt;/p&gt;
&lt;p&gt;To be fair, it works. It’s not bad at all.
But it is not native, and it does not feel as good as the development experience in macOS&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#user-content-fn-linux&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2&gt;Bottom Line&lt;/h2&gt;
&lt;p&gt;To finish positively, I believe Windows is not &lt;em&gt;terrible&lt;/em&gt;.
Microsoft just needs to invest a little less into Copilot and a little more into &lt;strong&gt;quality&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Outlook&lt;/strong&gt; is great, but without a subscription, the default apps feel lacking compared to Google or Apple.&lt;/li&gt;
&lt;li&gt;If Microsoft looked at the best parts of the Apple ecosystem, they could catch up fast.&lt;/li&gt;
&lt;li&gt;They have everything needed to make this OS great, they just need to focus on users, UX, and quality.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will still load Windows from time to time to see if things change.
&lt;strong&gt;But for this PC, Arch Linux has definitely won.&lt;/strong&gt;&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Linux is outside of this comparison. It’s just 10x better for backend development, especially since all my servers run Linux. &lt;a href=&quot;https://safigo.dev/posts/2026-03-windows-after-macos/#user-content-fnref-linux&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>windows</category><category>macos</category><category>linux</category><category>os</category></item><item><title>Project-based local environment with mise-en-place</title><link>https://safigo.dev/posts/2026-03-local-env-with-mise/</link><guid isPermaLink="true">https://safigo.dev/posts/2026-03-local-env-with-mise/</guid><description>Introduction to a project-based local environment with mise-en-place</description><pubDate>Sat, 14 Mar 2026 01:17:36 GMT</pubDate><content:encoded>&lt;h2&gt;Table of contents&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;&lt;details&gt;&lt;summary&gt;Open Table of contents&lt;/summary&gt;&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#development-environment&quot;&gt;Development environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#testing-solutions&quot;&gt;Testing solutions&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#virtual-machine-with-file-sync&quot;&gt;Virtual machine with file sync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#virtual-machine-with-ide&quot;&gt;Virtual machine with IDE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#development-containers&quot;&gt;Development Containers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#local-and-native-experience&quot;&gt;Local and native experience&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#mise-en-place&quot;&gt;mise-en-place&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#simplification-by-mise-en-place&quot;&gt;Simplification by mise-en-place&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#my-use-cases&quot;&gt;My use cases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#global-tools&quot;&gt;Global tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2026-03-local-env-with-mise/#bottom-line&quot;&gt;Bottom line&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;/details&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Development environment&lt;/h2&gt;
&lt;p&gt;Do you work on open source, commercial projects, or several projects at once?&lt;/p&gt;
&lt;p&gt;Many of us do, usually with a mix of all of them.
For example, this blog is built with Astro, and it can become outdated if I do not touch it for a while.
How can we make sure builds stay reproducible and still work years later?&lt;/p&gt;
&lt;p&gt;Modern development relies on a few layers of version management:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dependency management, like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;package.json&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;go.mod&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Cargo.toml&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Deployment environments like Docker/Podman, cloud VM images, etc.&lt;/li&gt;
&lt;li&gt;OS package managers like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;pacman&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;apt&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;yum&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of this works well when we target isolated environments.
We build one cloud instance per service, one Dockerfile per app, and one dependency manifest per project.&lt;/p&gt;
&lt;p&gt;But in my local development environment, I still struggle.&lt;/p&gt;
&lt;p&gt;Most of the time I use macOS, but recently I also started using Arch Linux.
Both operating systems have great package managers.
On macOS I use &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;, on Arch Linux, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;pacman&lt;/code&gt; and AUR are more than enough for me.&lt;/p&gt;
&lt;p&gt;But when I work on different projects, they have different requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Different compiler versions&lt;/li&gt;
&lt;li&gt;Extra tools, such as &lt;a href=&quot;https://github.com/amacneil/dbmate&quot;&gt;dbmate&lt;/a&gt;, &lt;a href=&quot;https://pre-commit.com/&quot;&gt;pre-commit&lt;/a&gt;, &lt;a href=&quot;https://prek.j178.dev/&quot;&gt;prek&lt;/a&gt;, &lt;a href=&quot;https://biomejs.dev/&quot;&gt;biome&lt;/a&gt;, &lt;a href=&quot;https://golangci-lint.run/&quot;&gt;golangci-lint&lt;/a&gt;, etc.&lt;/li&gt;
&lt;li&gt;Project-specific configuration requirements, like environment variables and bootstrap scripts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the most frustrating part: versions must be exact.
Many tools are not backward compatible (especially linters and language toolchains), so one update can break expected behavior.&lt;/p&gt;
&lt;h2&gt;Testing solutions&lt;/h2&gt;
&lt;p&gt;Over the years, different teams I worked with tried many ways to solve this and build a reproducible environment.&lt;/p&gt;
&lt;h3&gt;Virtual machine with file sync&lt;/h3&gt;
&lt;p&gt;In my experience, the most obvious solution was a preconfigured project VM.
I had to configure source synchronization and run everything remotely.&lt;/p&gt;
&lt;p&gt;This works in many cases, but it is not very comfortable, and everyone depends on a good internet connection.
If you need to upload something large (I can only imagine uploading &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;node_modules&lt;/code&gt;. I would run &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;pnpm install&lt;/code&gt; directly on the server),
it is painful. It takes time, and sometimes it fails entirely.&lt;/p&gt;
&lt;p&gt;Remote debugging is a separate topic, but it is rarely a pleasant experience.&lt;/p&gt;
&lt;p&gt;It also does not solve outdated projects well, where you need an older version of &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Python&lt;/code&gt;.
That can mean one VM per project if it falls outside the team’s default stack.&lt;/p&gt;
&lt;p&gt;But most importantly, it’s not what I personally prefer.&lt;/p&gt;
&lt;p&gt;I want to have a native local experience.
If I want to debug something, it just works.
I can work without internet, or with an unstable connection.
I want to get the best experience from my IDE.&lt;/p&gt;
&lt;p&gt;It is hard to avoid LLMs now. If I use them (and many companies expect that), I still want a native local workflow.&lt;/p&gt;
&lt;p&gt;In short, I have never had a truly pleasant experience using a remote instance as my main development environment.&lt;/p&gt;
&lt;h3&gt;Virtual machine with IDE&lt;/h3&gt;
&lt;p&gt;This is a relatively new idea for many developers, but not for people used to working in Vim or Emacs over terminals.&lt;/p&gt;
&lt;p&gt;Right now we have many options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/gitpod-io/gitpod&quot;&gt;Gitpod&lt;/a&gt; - I used it when they had just started&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/codespaces&quot;&gt;GitHub Codespaces&lt;/a&gt; - I tried it, but it feels expensive for personal use&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/remote/vscode-server&quot;&gt;Visual Studio Code Server&lt;/a&gt; - also an option, but not all extensions are available&lt;/li&gt;
&lt;li&gt;[N]Vim or Emacs through SSH with TMUX&lt;/li&gt;
&lt;li&gt;Google internal corporate development experience&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these are great, but they work best for companies ready to manage developer environments with templates.&lt;/p&gt;
&lt;p&gt;They are often too expensive for personal use, and they still require internet access.
Maybe I am old-fashioned, but sometimes I want to work offline.&lt;/p&gt;
&lt;p&gt;I’m sure many people will go for it, but it’s not for me, at least for today.&lt;/p&gt;
&lt;h3&gt;Development Containers&lt;/h3&gt;
&lt;p&gt;Another obvious solution is containers.&lt;/p&gt;
&lt;p&gt;The first time I tried this approach, a colleague suggested Vagrant as a dev environment.
To be fair, it was workable, but that was more than 10 years ago, and it was less usable than most options today.&lt;/p&gt;
&lt;p&gt;Since Docker was released, deployment workflows changed significantly.
We can now build a container and run it much more easily and cheaply across projects.&lt;/p&gt;
&lt;p&gt;Not Docker itself, but &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Dockerfile&lt;/code&gt; was a revolution!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://containers.dev/&quot;&gt;Development Containers&lt;/a&gt; can work well, but they still do not feel as smooth as a truly local setup.&lt;/p&gt;
&lt;p&gt;I still use Development Containers from time to time, but lately I almost completely migrated to a native experience.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;💡 Tip: use isolated environments like virtual machines, containers, or devcontainers when running untrusted code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Local and native experience&lt;/h3&gt;
&lt;p&gt;I used to just install all required tools using Homebrew.
It just works, no quirks.&lt;/p&gt;
&lt;p&gt;Until it does not.&lt;/p&gt;
&lt;p&gt;A recent example: I had a website built with &lt;a href=&quot;https://gohugo.io/&quot;&gt;[Go]Hugo&lt;/a&gt; that I had not touched for years, except for small content updates.
Some articles were added, edited, or removed. But &lt;a href=&quot;https://gohugo.io/&quot;&gt;[Go]Hugo&lt;/a&gt; is not strongly backward compatible.
When I come back to that site, it often does not build locally until I fix things. I cannot compile something that used to work.&lt;/p&gt;
&lt;p&gt;I had the same experience with Python, PHP, Ruby, and others. It is not just Hugo.&lt;/p&gt;
&lt;p&gt;So the problem is clear.
I can pin app dependencies to keep runtime behavior stable.
But that does not fully solve the local development environment itself.&lt;/p&gt;
&lt;p&gt;At one point, I wanted to try monorepo tooling.
I thought a monorepo might fit one of my projects.
I wired many separate &lt;a href=&quot;https://taskfile.dev/&quot;&gt;Taskfile&lt;/a&gt; files together by including them in each other.&lt;/p&gt;
&lt;p&gt;After some research for something that worked for me (outside the JS/TS world), I found &lt;a href=&quot;https://moonrepo.dev/&quot;&gt;moonrepo&lt;/a&gt; with
&lt;a href=&quot;https://moonrepo.dev/proto&quot;&gt;proto&lt;/a&gt;, and surprisingly it could pull various dependencies automatically.
So, I did not need to configure an environment for my app.&lt;/p&gt;
&lt;p&gt;It downloaded and installed required languages and additional tools with specified versions.&lt;/p&gt;
&lt;p&gt;I was happy with it at first, but it was not enough. Some tools I needed were not available, so I still had to install them
separately, which brought back the same problem.&lt;/p&gt;
&lt;p&gt;For me, it was a partial solution, not a complete one. It is definitely nice, but &lt;a href=&quot;https://moonrepo.dev/proto&quot;&gt;proto&lt;/a&gt;
still feels unfinished.&lt;/p&gt;
&lt;h2&gt;mise-en-place&lt;/h2&gt;
&lt;p&gt;Then I discovered &lt;a href=&quot;https://mise.jdx.dev/&quot;&gt;mise&lt;/a&gt;.
It felt like a better fit, with even more potential as I learned it.&lt;/p&gt;
&lt;p&gt;Initially I started with a simple &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;[tools]&lt;/code&gt; block, like this:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;toml&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;24.14&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;10.32&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;go&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;1.25&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;golangci-lint&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;2.11&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rust&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;1.94&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After configuring my Fish shell (you can check my &lt;a href=&quot;https://github.com/safigo/dotfiles/blob/main/.chezmoiscripts/run_once_000-install-mise.sh.tmpl&quot;&gt;dotfiles repo&lt;/a&gt;),
it just worked:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;fish&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;#!/usr/bin/env fish&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;brew&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; install mise&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;mise activate fish | source&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ~/.config/fish/conf.d/mise.fish&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;cd&lt;/code&gt; into a directory and get all required tools with the right versions.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;fish&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; prek&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; --version&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;fish&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: Unknown command: prek&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; cd&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; safigo.dev&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; prek&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; --version&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;prek&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; 0.3.5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Plugins for JetBrains IDEs and Visual Studio Code significantly improve the experience.&lt;/p&gt;
&lt;p&gt;You simply create a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;mise.toml&lt;/code&gt; configuration (&lt;a href=&quot;https://mise.jdx.dev/configuration.html#mise-toml&quot;&gt;or another available way&lt;/a&gt;)
and everyone who has configured &lt;strong&gt;mise&lt;/strong&gt; gets a reproducible local development environment and build results.&lt;/p&gt;
&lt;p&gt;You can install tools from many sources, including &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;npm&lt;/code&gt; and GitHub.
This is one of its most important features. So far, I have not found a tool I need that I cannot install with &lt;strong&gt;mise&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Simplification by mise-en-place&lt;/h3&gt;
&lt;p&gt;Before &lt;strong&gt;mise&lt;/strong&gt; I used to have &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;pyenv&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;pyautoenv&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;nvm&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;goenv&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;rustup&lt;/code&gt;, etc.
All of that needed to be configured and kept working.&lt;/p&gt;
&lt;p&gt;Later I discovered tools like &lt;a href=&quot;https://github.com/astral-sh/uv&quot;&gt;uv&lt;/a&gt; and &lt;a href=&quot;https://github.com/Schniz/fnm&quot;&gt;fnm&lt;/a&gt;
that simplified my environment significantly, but they are still far from &lt;strong&gt;mise&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;mise&lt;/strong&gt; is simply the next level, somewhere between a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Brewfile&lt;/code&gt; and a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Security&lt;/h3&gt;
&lt;p&gt;As I mentioned earlier, &lt;strong&gt;never run untrusted repositories&lt;/strong&gt;, and &lt;strong&gt;DO NOT&lt;/strong&gt; use &lt;strong&gt;mise&lt;/strong&gt; with them.&lt;/p&gt;
&lt;p&gt;By default, &lt;strong&gt;mise&lt;/strong&gt; does not allow dependency installation or environment switching until you trust the directory/project
by running &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;mise trust&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Be careful, since &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;mise&lt;/code&gt; can execute code during &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;mise install&lt;/code&gt; and maybe even when you &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;cd&lt;/code&gt; there,
though I have not fully explored all such hooks yet.&lt;/p&gt;
&lt;h2&gt;My use cases&lt;/h2&gt;
&lt;p&gt;I want a reproducible environment when I return to my own projects or start working on someone else’s project, old or new.&lt;/p&gt;
&lt;p&gt;I use various tools that can be specific to my preferences.&lt;/p&gt;
&lt;p&gt;Here is an example from my blog setup (this is the first post here):&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;toml&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[tools]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;# https://github.com/nodejs/node&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;24.14&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;# https://github.com/pnpm/pnpm&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;10.32&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;# https://github.com/j178/prek&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;prek&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;0.3&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; postinstall&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;prek install&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;# https://github.com/biomejs/biome&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;github:biomejs/biome&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;2.4.6&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; version_prefix&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;@biomejs/biome@&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; bin&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;biome&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[tasks.install]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;pnpm install --frozen-lockfile&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;alias&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[tasks.dev]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;pnpm run dev&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;alias&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[tasks.lint]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;biome check&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[tasks.lint-fix]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;biome check --write&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[env]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ENV&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; # Just an example&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, a contributor only needs to run &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;mise install&lt;/code&gt;, and everything I expect will be installed.
It also includes a &lt;strong&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;post-install&lt;/code&gt; script&lt;/strong&gt; that sets up the &lt;strong&gt;pre-commit&lt;/strong&gt; hook automatically for anyone who contributes.&lt;/p&gt;
&lt;p&gt;Another interesting line in this config is:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;toml&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;github:biomejs/biome&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;2.4.6&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; version_prefix&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;@biomejs/biome@&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; bin&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;biome&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It does not use a default &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;biome&lt;/code&gt; plugin and instead downloads from GitHub, even though Biome releases use unusual tags like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;@biomejs/biome@2.4.6&lt;/code&gt;.
Even when a repository uses unusual version tags, &lt;strong&gt;mise&lt;/strong&gt; can strip prefixes and rename the binary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why don’t I use npm to fetch &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;biome&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I used to. It worked well, but it only covers a subset of tools.
&lt;strong&gt;mise&lt;/strong&gt; feels native and consistent across my projects: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;go&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;rust&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;nodejs&lt;/code&gt;.
I see no reason why &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;biome&lt;/code&gt; would be so &lt;em&gt;&lt;strong&gt;unique&lt;/strong&gt;&lt;/em&gt; to install it differently from other tools.&lt;/p&gt;
&lt;h2&gt;Global tools&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Mise&lt;/strong&gt; also supports to install tools on a global level, similar to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;npm&lt;/code&gt; or &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;go install&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But why? We already have our package manager and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;npm&lt;/code&gt; and other tools!&lt;/p&gt;
&lt;p&gt;There are few reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Your tool is not available in your particular package manager&lt;/li&gt;
&lt;li&gt;You want to have dotfiles that will install something independently on your OS and Linux distro&lt;/li&gt;
&lt;li&gt;You’d prefer to have the latest version of tools pulling directly from their direct repo.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given all of that, Mise can be handy for global (user) level tool management as wel las project-level.&lt;/p&gt;
&lt;h2&gt;Bottom line&lt;/h2&gt;
&lt;p&gt;I know everyone is focused on AI/LLM right now. But foundational tools are still here: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;libc&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;gcc&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;go&lt;/code&gt;,
&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;python&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;makefile&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;taskfile&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;curl&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;brew&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;pacman&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;apt&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;mise&lt;/code&gt;, and more.&lt;/p&gt;
&lt;p&gt;AI may replace some tools, some programs, maybe even some professions, but there will always be a foundation.
Something still has to run the infrastructure where AI operates.&lt;/p&gt;
&lt;p&gt;I see &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;mise&lt;/code&gt; as closer to those fundamental tools and services that power development infrastructure, rather than just
another hype tool.&lt;/p&gt;
&lt;p&gt;I encourage my colleagues to integrate it into their workflows. So far, I have received only positive feedback.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>development</category><category>tools</category></item><item><title>Vibe Coding Initiation</title><link>https://safigo.dev/posts/2025-10-10-vibe-coding-initiation/</link><guid isPermaLink="true">https://safigo.dev/posts/2025-10-10-vibe-coding-initiation/</guid><description>My first experience with real vibe coding.</description><pubDate>Sat, 11 Oct 2025 02:32:53 GMT</pubDate><content:encoded>&lt;h2&gt;My experience with vibe coding&lt;/h2&gt;
&lt;p&gt;Everyone talks about vibe coding. There are many tools that promote it, and many people claim to practice it.&lt;/p&gt;
&lt;p&gt;I’ve tried it multiple times with various tools, but it never really worked.
Actually, it’s not a complete truth; it worked until it did not.&lt;/p&gt;
&lt;p&gt;The actual issue was always the amount of generated code and the quality of the results.&lt;/p&gt;
&lt;p&gt;But I’ve found an ideal task for vibe coding - redesign this blog.
I wanted to change the theme, but since I’m not a designer, I needed some help.&lt;/p&gt;
&lt;p&gt;Firstly, I asked to review the codebase and generate a README for it.
Afterwards, I asked to make the website more modern and appealing.&lt;/p&gt;
&lt;p&gt;Starting from that, it took multiple iterations to get to the final result.
In some cases, it generated a lot of redundant CSS; in some cases, it was quite good.
Usually, the model could fix issues and solve small tasks I asked it to do in one or a few iterations.&lt;/p&gt;
&lt;p&gt;Apart from CSS quality, the main task was done. It redesigned the blog to a more modern look.
But some links did not contain a hover effect, even though all others had.&lt;/p&gt;
&lt;p&gt;So, I asked to fix it, describing the issue and showing the example (the page and the text that was affected).
It took five or even more iterations until I gave up, since the LLM had generated &lt;strong&gt;Exceptions in CSS for the links&lt;/strong&gt; and it never really worked.&lt;/p&gt;
&lt;p&gt;OK, I thought to myself, let’s try to fix it manually.
I opened two separate windows and started to compare; all styles were the same, except the line that did not work was multi-line, while the others were single line.
I found a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;width: 100%&lt;/code&gt; that did not work in this case.&lt;/p&gt;
&lt;p&gt;When I asked to fix it, the LLM fixed it with no issues.&lt;/p&gt;
&lt;p&gt;Every iteration it tried to fix the issue, it generated more and more CSS that made an effect on other places.&lt;/p&gt;
&lt;p&gt;Meanwhile, the final result was quite good; I decided to go to the next steps and clean it up.&lt;/p&gt;
&lt;h2&gt;Cleaning CSS&lt;/h2&gt;
&lt;p&gt;The first step was to ask the LLM to clean CSS from unused styles and make it more compact and efficient.
It did some job. Some CSS was deleted, and everything works well.&lt;/p&gt;
&lt;p&gt;Why not try to make it even better? Let’s ask again.&lt;/p&gt;
&lt;p&gt;The second iteration started to break the website, so I reverted to the previous version.&lt;/p&gt;
&lt;p&gt;But even when it was done, the website required some cleaning, where I decided to jump in and fix it manually.
It took me around 30 minutes to remove all styles I did not like in a design and keep it more minimalistic.&lt;/p&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;When I look at the final CSS, I can clearly state that it’s not perfect. Maybe it’s even not efficient, but it works well and looks good enough.&lt;/p&gt;
&lt;p&gt;I think I’ve started to understand the Vibe Coding concept, and I can say that it’s not for everyone.
Until LLMs won’t be able to understand the context and the task fully, it will require a lot of iterations and human intervention to do the job. And we did not start speaking about complex tasks.&lt;/p&gt;
&lt;p&gt;I’ve tried LLMs with complex tasks very often, and I can say that it’s not working well. For me, it has never worked well yet.&lt;/p&gt;
&lt;p&gt;But for simple tasks, specifically from an area you are not familiar with, it can be a great help.
It’s not a hired developer, but it feels like an assistant that can do some job for you. It can review your code, generate documentation, fix small issues, and brainstorm ideas.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>ai</category><category>vibe-coding</category><category>development</category></item><item><title>Dotfiles with Chezmoi</title><link>https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/</link><guid isPermaLink="true">https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/</guid><description>Manage your dotfiles effortlessly with Chezmoi.</description><pubDate>Wed, 08 Oct 2025 04:54:17 GMT</pubDate><content:encoded>&lt;h2&gt;Dotfiles Management&lt;/h2&gt;
&lt;p&gt;I’m not a fan of complex workflows for personal use, simpler is better.
Over many years I’ve seen countless posts and repositories about dotfiles, and often they felt highly customized.
Frequently, people provide their own bash scripts to install and manage dotfiles.&lt;/p&gt;
&lt;p&gt;That’s not my approach.
After many years in software engineering, I appreciate the power of open source and well-designed, well-tested solutions.
Even a small library should be thoughtfully designed and carefully tested — so why reinvent the wheel?&lt;/p&gt;
&lt;p&gt;I don’t remember how I found chezmoi&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/#user-content-fn-chezmoi&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, but it was simple and straightforward.
It has good documentation, is actively maintained, and offers many features.&lt;/p&gt;
&lt;p&gt;Although I felt comfortable with chezmoi&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/#user-content-fn-chezmoi&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, I forgot about it several times.
Each time I returned, I was pleasantly surprised at how useful and well-maintained it still was.&lt;/p&gt;
&lt;p&gt;So I use it, and I recommend it to others — everyone is happy.
Since it has proven itself many times, I can confidently recommend it.&lt;/p&gt;
&lt;h2&gt;Quick walkthrough&lt;/h2&gt;
&lt;p&gt;Chezmoi&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/#user-content-fn-chezmoi&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; has many features, and most importantly, excellent documentation.
I won’t repeat that documentation here. Instead, here’s a quick overview of how I suggest getting started.&lt;/p&gt;
&lt;p&gt;As an example, we’ll install my dotfiles from my &lt;a href=&quot;https://github.com/safigo/dotfiles&quot;&gt;dotfiles repo&lt;/a&gt; and assume you’re using macOS.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install through Homebrew: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;brew install chezmoi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Initialize chezmoi with my repo: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;chezmoi init git@github.com:aohorodnyk/dotfiles.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Apply dotfiles to your home directory: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;chezmoi apply&lt;/code&gt;, and write your password if prompted.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it — you’ll have my dotfiles in your home directory.&lt;/p&gt;
&lt;p&gt;To open the cloned repo, run &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;chezmoi cd&lt;/code&gt; — it will open the repo in your terminal.&lt;/p&gt;
&lt;p&gt;Read docs, it’s really powerful!&lt;/p&gt;
&lt;h2&gt;Good luck with your dotfiles management!&lt;/h2&gt;
&lt;p&gt;This note isn’t just about chezmoi — it’s about the value of exploring and learning new technologies, and of continual self-improvement.
Even after 10, 20, or 30 years of experience, you can still learn and grow.&lt;/p&gt;
&lt;p&gt;Feel free to reach out if you have any questions or need assistance.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/twpayne/chezmoi/&quot;&gt;Repo&lt;/a&gt; and &lt;a href=&quot;https://chezmoi.io/&quot;&gt;website&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/#user-content-fnref-chezmoi&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/#user-content-fnref-chezmoi-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2025-10-07-dotfiles-with-chezmoi/#user-content-fnref-chezmoi-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-3&quot;&gt;↩&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>dotfiles</category><category>tools</category><category>chezmoi</category></item><item><title>KISS for websites below 14KB</title><link>https://safigo.dev/posts/2025-09-19-pages-below-14kb/</link><guid isPermaLink="true">https://safigo.dev/posts/2025-09-19-pages-below-14kb/</guid><description>One more reason to keep your website simple and lightweight.</description><pubDate>Sat, 20 Sep 2025 01:42:47 GMT</pubDate><content:encoded>&lt;h2&gt;And here we go again&lt;/h2&gt;
&lt;p&gt;How many times have you heard that your website should be lightweight and fast?
How many times have “geeks” asked to remove unnecessary JavaScript and CSS?&lt;/p&gt;
&lt;p&gt;And here we go again, one more reason to keep your website simple and lightweight by referring to the &lt;a href=&quot;https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/&quot;&gt;Why your website should be under 14kB in size&lt;/a&gt; article.&lt;/p&gt;
&lt;p&gt;When I read about it, it just flashed in my mind that some websites just feel blazing fast.
For example, a blog you read this article on.
It does not feel like it is loaded, it just appears.&lt;/p&gt;
&lt;p&gt;OK, I thought to myself. Let’s check the actual size of the page. It’s 5-7KB. Hm… Let’s check some other blogs.&lt;/p&gt;
&lt;p&gt;But when I went through other websites, the difference felt (especially on slower connections).
OK then, how hard is it to keep everything below 14KB?&lt;/p&gt;
&lt;p&gt;Actually, 14KB is a lot of text.
If we keep it simple, the design would be much more readable and the size would be small.
My blog is a theme I found on the internet and slightly modified it.
But investing a little bit of time may make the size even smaller.&lt;/p&gt;
&lt;p&gt;My bottom line would be “geeky” and very predictable.
Keep it simple, keep it small, keep it fast.
I want to see more simple sites and blogs.
Use static site generators, not WordPress or other CMS.&lt;/p&gt;
&lt;p&gt;If you don’t earn money from your website, why make it complex?&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>web-development</category><category>performance</category></item><item><title>Capturing traffic with Golang</title><link>https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/</link><guid isPermaLink="true">https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/</guid><description>Capturing traffic with custom logic on Golang. Don&apos;t forget to save pcap-compatible file.</description><pubDate>Sat, 31 Aug 2024 20:43:16 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Most of the people from Software Engineering world heard about &lt;a href=&quot;https://www.tcpdump.org&quot;&gt;TCPDump&lt;/a&gt;, &lt;a href=&quot;https://www.wireshark.org&quot;&gt;WireShark&lt;/a&gt;, etc.
And most likely you have heard about &lt;strong&gt;libpcap&lt;/strong&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fn-libpcap&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; library developed by &lt;a href=&quot;https://www.tcpdump.org&quot;&gt;TCPDump&lt;/a&gt; team to capture traffic and used by &lt;a href=&quot;https://www.wireshark.org&quot;&gt;Wireshark&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;This library&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fn-libpcap&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; provides a flexible interface to capture a traffic from a network interface and process it in a code. It provides a flexibility to write performant code and include as much business logic as needed to collect only required data.&lt;/p&gt;
&lt;p&gt;Recently I’ve identified a task where it would be a good idea to collect required packets, analyze them and save for the future manual review. To review manually &lt;a href=&quot;https://www.wireshark.org&quot;&gt;WireShak&lt;/a&gt; can be used to load pcap file and manually review the collected packets using nice UI.&lt;/p&gt;
&lt;p&gt;And the most important part, why Go? Go is a nice simple enough language to write code and support it by multiple team members. It’s much more safe than C and C++ and requires much less experience for other people to support it without unexpected surpises. Until we don’t have requirements when we HAVE TO go with much performant language (C, C++, rust, etc.), I prefer to choose Golang.&lt;/p&gt;
&lt;h2&gt;Task definition&lt;/h2&gt;
&lt;p&gt;Before we will do something, it would be great to understand, what do we want to achieve in a result? Let’s define a short list of requirements.&lt;/p&gt;
&lt;h3&gt;Requirements&lt;/h3&gt;
&lt;p&gt;To keep implementation as simple as possible, let’s define only few points:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We want to collect outcoming traffic&lt;/li&gt;
&lt;li&gt;Let’s collect IPv4 traffic&lt;/li&gt;
&lt;li&gt;Ignore private networks traffic&lt;/li&gt;
&lt;li&gt;And let’s keep UDP packets&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These simple few points will be enough to get an idea on how to use libpcap&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fn-libpcap&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; from Golang.
After that it’s only matter of imagination on what logic will be added on top of that.&lt;/p&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;Before we will start, let’s define that code is not suppose to be a production ready. Our goal is to see the minimum example and test that it works well.&lt;/p&gt;
&lt;p&gt;We will use these libraries:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;slog&lt;/code&gt; for loggin&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;github.com/google/gopacket&lt;/code&gt; for capturing packets and formatting &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;pcap&lt;/code&gt; file format&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An interface in the future code will be &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;eth0&lt;/code&gt;, even though most likely your system will have a different interaface name.&lt;/p&gt;
&lt;h3&gt;Working code&lt;/h3&gt;
&lt;p&gt;This is the code with comments you can copy and try in your own environment.
Since we use &lt;strong&gt;libpcap&lt;/strong&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fn-libpcap&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, our application will use &lt;strong&gt;CGO&lt;/strong&gt; and we will need to run the app from &lt;strong&gt;root&lt;/strong&gt; user.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;bytes&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;log/slog&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;os&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;github.com/google/gopacket&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;github.com/google/gopacket/layers&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;github.com/google/gopacket/pcap&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;github.com/google/gopacket/pcapgo&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;	interfaceName&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;eth0&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;	snaplen&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;       =&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1500&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Running our applicaiton...&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// Get handler attached to an interface.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	handle&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; pcap&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;OpenLive&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;interfaceName&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;snaplen&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;pcap&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;BlockForever&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not OpenLive&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		os&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Exit&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	iface&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; net&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;InterfaceByName&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;interfaceName&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not OpenLive&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		os&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Exit&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// Start new Source reader.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	source&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; gopacket&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;NewPacketSource&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;handle&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;handle&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;LinkType&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// This is suppose to be a file writer, but we will use memory, just for simplification.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fileWriter&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;NewBuffer&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	pcapWriter&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; pcapgo&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;NewWriterNanos&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fileWriter&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; pcapWriter&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WriteFileHeader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;snaplen&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;handle&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;LinkType&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not write pcap header&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		os&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Exit&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// Reading packages.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; packet&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; source&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Packets&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;		// Filter by outcoming traffic only.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;		// To filter it, we need to compare MAC addresses from out interface and source MAC.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;		// To access a mac Address we need to get an Ethernet layer.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		layer&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; packet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Layer&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;layers&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;LayerTypeEthernet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		ethernet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; layer&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.(&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;layers&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Ethernet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;			slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not get Ethernet layer&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;			continue&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;bytes&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Equal&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ethernet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;SrcMAC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;iface&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;HardwareAddr&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;			// Our interface did not send this packet. It&apos;s not outcoming.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;			continue&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;		// Now we need to identify IPv4 layer.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		layer&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; packet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Layer&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;layers&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;LayerTypeIPv4&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		ipv4&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; layer&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.(&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;layers&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;IPv4&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;			// It&apos;s not IPv4 traffic.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;			continue&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ipv4&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;DstIP&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;IsPrivate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;			// Do not collect private traffic.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;			continue&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ipv4&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Protocol&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; layers&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;IPProtocolUDP&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;			// Ignore not UDP protocol.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;			continue&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; pcapWriter&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WritePacket&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;packet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Metadata&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;CaptureInfo&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;packet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;			slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not write a packet to a pcap writer&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;			continue&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Stored packet&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Any&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;packet&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;packet&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;		// Let&apos;s collect ONLY 100K bytes, just for example perposes.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; fileWriter&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Len&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 100000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;			break&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;We have successfuly collected bytes&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slog&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;bytes&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fileWriter&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Len&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And after running there the truncated output looks like that:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;2024/08/31 13:35:36 INFO Running our applicaiton...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;2024/08/31 13:37:48 INFO Stored packet packet=&quot;PACKET: 105 bytes, wire length 105 cap length 105 ...&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;2024/08/31 13:37:48 INFO Stored packet packet=&quot;PACKET: 1291 bytes, wire length 1291 cap length 1291 ...&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;2024/08/31 13:37:48 INFO We have successfuly collected bytes bytes=101018&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I hope this minimum example will help someone to start their jorney in this area using Go.&lt;/p&gt;
&lt;h2&gt;Afterword&lt;/h2&gt;
&lt;p&gt;If you meet any new requirements in your everyday tasks that you have no idea how to do. Don’t hasitate to ask people around, write me in a private and do your own research.&lt;/p&gt;
&lt;p&gt;Research and communication is a key to all problems solving.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;libpcap is a portable C/C++ library for network traffic capture &lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fnref-libpcap&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fnref-libpcap-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fnref-libpcap-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-3&quot;&gt;↩&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2024-08-31-golang-traffic-capturer/#user-content-fnref-libpcap-4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-4&quot;&gt;↩&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>networking</category><category>security</category></item><item><title>Customer metrics availability</title><link>https://safigo.dev/posts/2024-04-24-custom-metrics-availability/</link><guid isPermaLink="true">https://safigo.dev/posts/2024-04-24-custom-metrics-availability/</guid><description>It&apos;s time to start collecting customer metrics for all startups and pet projects.</description><pubDate>Thu, 25 Apr 2024 02:23:16 GMT</pubDate><content:encoded>&lt;h2&gt;Overengineering or not?&lt;/h2&gt;
&lt;p&gt;Often enough I share an idea that all new serverless platforms as well as simple cloud providers like Digital Ocean do not support customer metrics.
All the time I hear it’s not needed for non-enterprise customers and I ask for the feature due my overengineering mindset.&lt;/p&gt;
&lt;p&gt;But today I saw a blogpost in my RSS reader from &lt;a href=&quot;https://www.techemails.com/p/bill-gates-quality-experience&quot;&gt;Internal Tech Emails&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;From: Bill Gates
Sent: Thursday, October 19, 2000 3:02 PM
To: Will Poole
Cc: Jim Allchin; Eric Rudder
Subject: Quality experience and streaming media&lt;/p&gt;
&lt;p&gt;I don’t know how unique I am but my experience in clicking on streaming media stuff and seeing if it works is still less than 50%.&lt;/p&gt;
&lt;p&gt;For example the MSN home page talk about a golf match going on called the President’s cup. I click on that and then I click on this link:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://stream1.%5B...%5D.com/%5B...%5D/101700192418001.rm&quot;&gt;http://stream1.[…].com/[…]/101700192418001.rm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I get a message saying: “This document is not a RealAudio or RealVideo Document” “This is error 11. To learn more go to a real URL.&lt;/p&gt;
&lt;p&gt;This is so typical. I always get error messages when I click on Audio and Video.&lt;/p&gt;
&lt;p&gt;Just for fun I go to the home page and grab an MSNBC video clip:&lt;/p&gt;
&lt;p&gt;&amp;#x3C;&lt;a href=&quot;http://go.msn.com/CM/10002/default.asp?target=http://www.msnbc.com/%5B...%5D%5C%3E&quot;&gt;http://go.msn.com/CM/10002/default.asp?target=http://www.msnbc.com/[…]\&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I click and bizarrely I get a browser page and a video page - the lack of integration of the browser and the player is crazy.&lt;/p&gt;
&lt;p&gt;The browser page is fine but the video says buffering and 5 minutes later nothing has happened.&lt;/p&gt;
&lt;p&gt;We should go on a quality campaign. We should really collect error message reports from our servers.&lt;/p&gt;
&lt;p&gt;Something is very hard to set up or hard to track in this area. The quality is giving us a bad name.&lt;/p&gt;
&lt;p&gt;I guess I can keep sending all my failures along - the key point is that I haven’t seen any improvement.&lt;/p&gt;
&lt;p&gt;I have yet to have a good video experience.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Where Bill Gates asks for a solution to collect logs from different servers to monitor them.
It was ~24 years ago, Microsoft that is already big company with many customers and many servers, and they still don’t have a solution for this.&lt;/p&gt;
&lt;p&gt;The CEO experiences an issue with a production product, but there is not simple solution to look at metrics/logs/etc. to identify the reason of the issue. I’m sure it’s not the case in current Microsoft’s infrastructure.&lt;/p&gt;
&lt;p&gt;Moreover, there is no such cases even in small per projects or startups that just deployed a single serverless function to any serverless solution.
But why?&lt;/p&gt;
&lt;h2&gt;Available solutions&lt;/h2&gt;
&lt;p&gt;The main reason we have logs in any cloud provider is believement in this feature as essential part of any system.
In current environment we just expect to have it and the most of us will be surprised to find out that it’s not available.&lt;/p&gt;
&lt;p&gt;But what about metrics?&lt;/p&gt;
&lt;p&gt;Suprisingly, the most providers provide system metrics along with logs. We expect to have some high-level system metrics along with logs for every component of our system.
But, there is no such case for custom metrics.
The most of the providers do not provide a buildin solution for custom metrics in a service.&lt;/p&gt;
&lt;p&gt;We can try to explain it as an expensive solution, or not popular request from customers.
However, in my opinion, it’s because there is no the first provider who started to provide it.&lt;/p&gt;
&lt;p&gt;It’s only matter of time after the first big player who will provide it, other would copy and standardize the solution.
I’m waiting for the first serverless provider (Supabase? Firebase? Vercel?) to introduce it as a free (or cheap) additional service and it will be spread to all small and big cloud proviers at no time.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Why have I decided to write down my thoughts?&lt;/p&gt;
&lt;p&gt;I hope to engage someone to add this small, but really important feature to their platform.
I believe it will be a killer feature for the platform (at least for short period of time while it’s uniq their feature) as well as a great investment to our bright future of cloud services.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>metrics</category><category>engineering</category><category>monitoring</category></item><item><title>Signin with Apple with Expo&apos;s app.json</title><link>https://safigo.dev/posts/2024-04-13-expo-ios-enable-signin-with-apple/</link><guid isPermaLink="true">https://safigo.dev/posts/2024-04-13-expo-ios-enable-signin-with-apple/</guid><description>Learn how to enable Sign in with Apple for your Expo iOS app through app configuration.</description><pubDate>Sat, 13 Apr 2024 17:37:12 GMT</pubDate><content:encoded>&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Apple’s Sign in with Apple feature is a convenient way for users to sign in to your app without creating a new account. It provides a secure and private way to authenticate users and helps you comply with privacy regulations. If you are building an application to distribute on the App Store and you offer third-party sign-in options, you must include Sign in with Apple as an option.&lt;/p&gt;
&lt;p&gt;Expo team has made their own implementation of Sign in with Apple library &lt;a href=&quot;https://docs.expo.dev/versions/latest/sdk/apple-authentication/&quot;&gt;expo-apple-authentication&lt;/a&gt; that may work for you. I have never tried this library, but consider using itm before going through this article’s recommendations.&lt;/p&gt;
&lt;h2&gt;Firebase React Native library&lt;/h2&gt;
&lt;p&gt;In my application I’ve decided to use Firebase to authenticate users. Firebase provides a way to authenticate users using Apple’s Sign in with Apple feature. To enable this feature, you need to configure your app in the Apple Developer Console and Firebase Console.&lt;/p&gt;
&lt;p&gt;For React Native there is a cool implementation for Firebase integrations called &lt;a href=&quot;https://rnfirebase.io/&quot;&gt;react-native-firebase&lt;/a&gt;. It provides instructions and examples on how to integrate Firebase Authencation with Social Providers like Google, Facebook, Twitter, and Apple, etc.&lt;/p&gt;
&lt;p&gt;The library provides detailed instructions on how to configure all social networks authentication providers, but Sign In with Apple require some additional steps to be configured in Xcode. But since I play with Expo, I generate &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;ios&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;android&lt;/code&gt; folders automatically, and I don’t want to configure anything manually. Expo should provide a way to configure this automatically as all other parts of the app and the project.&lt;/p&gt;
&lt;h2&gt;Expo iOS app configuration&lt;/h2&gt;
&lt;p&gt;After a couple of ours of research, I’ve found a way to configure Sign in with Apple for Expo iOS app through app configuration (&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;app.json&lt;/code&gt;/&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;app.config.js&lt;/code&gt;/&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;app.cofngi.ts&lt;/code&gt;). Expo’s configuration paramerter has name &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;entitilements&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is an example on how to enable Sign In with Apple in Xcode project for auto-generated Expo iOS app:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;ios&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    &quot;entitlements&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      &quot;com.apple.developer.applesignin&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Default&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Funny part:&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;I tried to use different AI chats to get help with this issue, but they all were not able to help me.
Regular old-style search engines and GitHub/StackOverflow/Reddit/etc. are still the best way to get help with issues.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>expo</category><category>ios</category><category>apple-signin</category></item><item><title>List all ignored files in git</title><link>https://safigo.dev/posts/2023-11-28-list-all-ignored-files-in-git/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-11-28-list-all-ignored-files-in-git/</guid><description>Discover an easy way to list all ignored files in git with one simple command.</description><pubDate>Wed, 29 Nov 2023 06:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Recently, I’ve been working on a project where I, as usual, vendored my Golang dependencies by &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;go mod vendor&lt;/code&gt; command. I then added these files to git and pushed them to the remote repository.&lt;/p&gt;
&lt;p&gt;However, I noticed that the CI/CD pipeline was failing due to the presence of these files. I was puzzled as to why this was happening. I then realized that some files or directories were being ignored by git, and I had to find out which ones.&lt;/p&gt;
&lt;h2&gt;The Method&lt;/h2&gt;
&lt;p&gt;I was aware of the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;git status --ignored&lt;/code&gt; command, but it didn’t provide the desired output. I wanted to see the list of ignored files and directories, but the command only showed the ignored files that were already tracked by git. I needed to see all ignored files, including the untracked ones.&lt;/p&gt;
&lt;p&gt;I then discovered the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;git ls-files --others --ignored --exclude-standard&lt;/code&gt; command, which did exactly what I wanted. It listed all ignored files and directories, including the untracked ones. Where I could then see the files and directories that were being ignored by a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;.gitignore&lt;/code&gt; file generated by &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;gitignore.io&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;In troubleshooting a CI/CD hiccup during Golang dependency vendoring, a routine process led to unexpected complexities. Conventional Git commands fell short, prompting the discovery of git ls-files —others —ignored —exclude-standard. The culprit? A dynamically generated .gitignore from gitignore.io. This incident is a reminder of the dynamic nature of development workflows, where routine tasks can unearth unforeseen challenges, paving the way for continual learning.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>git</category><category>tools</category></item><item><title>Golang panics in libraries</title><link>https://safigo.dev/posts/2023-07-31-go-panic-libraries/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-07-31-go-panic-libraries/</guid><description>Should we panic in libraries? And why not?</description><pubDate>Tue, 01 Aug 2023 04:32:14 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;When I read about &lt;a href=&quot;https://golang.org/&quot;&gt;Golang&lt;/a&gt; for the first time, I was an active user of languages with exceptions, like &lt;a href=&quot;https://openjdk.org/&quot;&gt;Java&lt;/a&gt;, &lt;a href=&quot;https://www.php.net&quot;&gt;PHP&lt;/a&gt;, &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;, &lt;a href=&quot;https://www.ruby-lang.org/en/&quot;&gt;Ruby&lt;/a&gt;, etc.&lt;/p&gt;
&lt;p&gt;It was obvious that big projects handle their behaviour through exceptions and we can control flow through &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;try/catch&lt;/code&gt; blocks in parent call stack.&lt;/p&gt;
&lt;p&gt;Outside languages with exceptions I had some experience with other languages like &lt;a href=&quot;https://en.wikipedia.org/wiki/C_(programming_language)&quot;&gt;C&lt;/a&gt; or codebases that prohibit exceptions.&lt;/p&gt;
&lt;p&gt;Experience without exceptions, usually was less pleasant, because it applied many restrictions and limitations to the codebase.
Additionally, many of these codebases did not support return for multiple values, so the flow control had to be built through returning unsupported values (like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;-1&lt;/code&gt; for &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int&lt;/code&gt;s and null for references).
Because of these limitations, there were popular ways to handle these restrictions through reference parameters and &lt;em&gt;returning&lt;/em&gt; results through them.&lt;/p&gt;
&lt;h2&gt;Golang&lt;/h2&gt;
&lt;p&gt;There we are! We have met &lt;a href=&quot;https://golang.org/&quot;&gt;Golang&lt;/a&gt; for the first time.
The documentation and articles and bool suggest to use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; return value, instead of exceptions. More over, exceptions are not supported in Golang at all (or almost).&lt;/p&gt;
&lt;p&gt;By going through &lt;a href=&quot;https://golang.org/&quot;&gt;Golang&lt;/a&gt; documentation and the codebase, many people notice that there is a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; with &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;recover&lt;/code&gt;, that can be used as exceptions. These people write many articles, posts, and comments about how &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt;s in &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt;.
But &lt;a href=&quot;https://golang.org/&quot;&gt;Golang&lt;/a&gt; community always criticizes these thoughts and suggests to use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; returned value instead of &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt;. Moreover, those people share an opinion that &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; handling in &lt;a href=&quot;https://golang.org/&quot;&gt;Golang&lt;/a&gt; is much better than exceptions in other languages.&lt;/p&gt;
&lt;p&gt;Let’s try to understand why it is so.&lt;/p&gt;
&lt;h2&gt;Error handling&lt;/h2&gt;
&lt;p&gt;Before we will compare exceptions and error handling from &lt;a href=&quot;https://golang.org/&quot;&gt;Golang&lt;/a&gt;, let’s try to go through the main ways to handle errors.&lt;/p&gt;
&lt;p&gt;There are three of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Return error from the function.&lt;/li&gt;
&lt;li&gt;Throw error through current stack of calls until someone will catch it.&lt;/li&gt;
&lt;li&gt;Stop execution of the program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All these ways are used in many different languages in parallel and non of them is better than others.&lt;/p&gt;
&lt;h3&gt;Return error from the function&lt;/h3&gt;
&lt;p&gt;This way is the first way I’ve seen when I started to learn programming in &lt;a href=&quot;https://en.wikipedia.org/wiki/C_(programming_language)&quot;&gt;C&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Assembly_language&quot;&gt;Assembly&lt;/a&gt;. It is the most obvious way to handle errors, because we can just agree that some special value will be returned in case of error. In case of C it is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;-1&lt;/code&gt; for &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int&lt;/code&gt;s and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;NULL&lt;/code&gt; for references. Sometimes it cam be some &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; parameter that will be filled with error value by reference.&lt;/p&gt;
&lt;p&gt;The best thing about this way is that it is very simple and easy to understand. It increases readability of the code and makes it easy to debug by printing a value or putting debugger on the line to see the scope of variables.
In case of C it was kinda confusing, since we did not have predictable way to work with errors and we had to check the documentation of each function to understand how it handles errors.&lt;/p&gt;
&lt;p&gt;In case of &lt;em&gt;modern&lt;/em&gt; languages like &lt;a href=&quot;https://golang.org/&quot;&gt;Golang&lt;/a&gt;, &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;, etc. we have a predefined way to work with error handling by specific &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; types and rules on how to use them. It improves readability and simplifies interfaces of functions.&lt;/p&gt;
&lt;p&gt;Basically all of the changes around it are just cosmetic that make huge difference, but concept is still the same.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Return error flow diagram&quot; width=&quot;670&quot; height=&quot;727&quot; src=&quot;https://safigo.dev/_astro/2023-07-31-go-panic-libraries-diagrams-return-error-flow.BO6kA92F_ZdtOPQ.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the diagram above we can see the flow of the program that uses this approach to handle errors.
Short explanation of the diagram:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function calls &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function calls &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function returns an error.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function checks return values from &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function and returns an error based on &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; from &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function checks return values from &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function and handles the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function can continue execution of the program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main idea of this approach a software developer should handle errors in each function in the call stack. And they can handle errors on any level of the call stack. If we do not know what to do on a specific level, we can just return an error to the caller and let them handle it.&lt;/p&gt;
&lt;h4&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Easy to understand.&lt;/li&gt;
&lt;li&gt;Easy to debug.&lt;/li&gt;
&lt;li&gt;Easy to use.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;In some cases this approach adds a boilerplate code.&lt;/li&gt;
&lt;li&gt;We need to thing about error handling in each call of a function.&lt;/li&gt;
&lt;li&gt;Every function in the call stack should handle errors and return them back to the caller, if needed.&lt;/li&gt;
&lt;li&gt;It can be simple to ignore an error without adding any handling for it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This handle of errors is used to guarantee that an error won’t be ignored and developer will always aware about an error.&lt;/p&gt;
&lt;h3&gt;Throw error through current stack of calls until someone will catch it&lt;/h3&gt;
&lt;p&gt;The main idea of this approach is to throw an error from a function up to callers stack until someone will catch it.
This way is the most popular way to handle errors in languages with exceptions like &lt;a href=&quot;https://openjdk.org/&quot;&gt;Java&lt;/a&gt;, &lt;a href=&quot;https://www.php.net&quot;&gt;PHP&lt;/a&gt;, &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;, &lt;a href=&quot;https://www.ruby-lang.org/en/&quot;&gt;Ruby&lt;/a&gt;, etc.&lt;/p&gt;
&lt;p&gt;By using this approach we can send a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; through call stack without adding any code and knowledge to intermediate levels. It simplifies development and removes requirements to thing about errors on the most levels of the call stack.&lt;/p&gt;
&lt;p&gt;Languages that support exceptions have a special keyword to throw an exception and to catch it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In case of &lt;a href=&quot;https://openjdk.org/&quot;&gt;Java&lt;/a&gt; and &lt;a href=&quot;https://www.php.net&quot;&gt;PHP&lt;/a&gt; it is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;throw&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;try/catch&lt;/code&gt; blocks.&lt;/li&gt;
&lt;li&gt;In case of &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt; it is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;raise&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;try/except&lt;/code&gt; blocks.&lt;/li&gt;
&lt;li&gt;In case of &lt;a href=&quot;https://www.ruby-lang.org/en/&quot;&gt;Ruby&lt;/a&gt; it is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;raise&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;begin/rescue&lt;/code&gt; blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But all of them have the same idea to control the execution flow: throw an exception and catch it on the level where we want handle it.&lt;/p&gt;
&lt;p&gt;With &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; it is a bit different. We do not have exceptions, but we have &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;recover&lt;/code&gt; functions.
Panics by themself are not control-flow statements, they are closer to &lt;a href=&quot;https://openjdk.org/&quot;&gt;Java&lt;/a&gt; &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Error&lt;/code&gt; type or &lt;a href=&quot;https://www.php.net&quot;&gt;PHP&lt;/a&gt; &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;ErrorException&lt;/code&gt; type. They are used to stop execution of the program in case of critical errors that are not related to business flow of the program.
In case of &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; we can use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; to throw an error and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;recover&lt;/code&gt; to catch it, but we can catch it only in &lt;a href=&quot;https://go.dev/tour/flowcontrol/12&quot;&gt;defer&lt;/a&gt; functions that are not linear execution code block and applies some limitations on top of it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Throw exception flow diagram&quot; width=&quot;716&quot; height=&quot;601&quot; src=&quot;https://safigo.dev/_astro/2023-07-31-go-panic-libraries-diagrams-exception.CU_83QeQ_9bJeA.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the diagram above we can find the flow of the program that uses this approach to handle errors.
Short explanation of the diagram:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function calls &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function calls &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function throws an &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function catches an &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; and handles it.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function can continue execution of the program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way to handle errors is used to simplify code writing and to reduce boilerplate code on intermediate levels of the call stack.&lt;/p&gt;
&lt;h4&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Easy to write new code.&lt;/li&gt;
&lt;li&gt;Zero boilerplate code on intermediate levels of the call stack.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;It is hard to understand where an error was thrown.&lt;/li&gt;
&lt;li&gt;It is hard to debug.&lt;/li&gt;
&lt;li&gt;It is hard to understand where an error will be caught, if it will be caught at all.&lt;/li&gt;
&lt;li&gt;If error was not caught, the program will be stopped during an execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Stop execution of the program&lt;/h3&gt;
&lt;p&gt;The most radical way to handle errors is to stop execution of the program in case of any error.
In the most languages it is done by using &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;exit&lt;/code&gt; function that stops execution of the program and returns an error code to the caller.
To handle errors there &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;assert&lt;/code&gt; function that checks a condition and stops execution of the program if it is not met.&lt;/p&gt;
&lt;p&gt;There is no way to recover the execution of the program after &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;exit&lt;/code&gt; or &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;assert&lt;/code&gt; functions were called. The one way error handling is used to stop execution in case of some critical errors that are not related to business flow of the program, but they also cannot be handled by the program.&lt;/p&gt;
&lt;p&gt;The simplest example of such error is a unsupported value of a parameter in command line interface. In this case we can just stop execution of the program and print an error message to the user.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Stop execution flow diagram&quot; width=&quot;954&quot; height=&quot;649&quot; src=&quot;https://safigo.dev/_astro/2023-07-31-go-panic-libraries-diagrams-stop-execution.KPlm36zo_2gHUak.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;Let’s review the flow of the program that uses this approach to handle errors. The diagram above shows the flow. In this diagram we added &lt;strong&gt;OS level&lt;/strong&gt; that represents the operating system that runs the program from an &lt;a href=&quot;https://en.wikipedia.org/wiki/Entry_point&quot;&gt;entry point&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-07-31-go-panic-libraries/#user-content-fn-entry_point&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Short explanation of the diagram:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;os&lt;/code&gt; calls an entry point of a program, usually by calling the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt; function calls &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; function calls &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function checks a condition and stops execution of the program.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;os&lt;/code&gt; receives an error code from the program and handles it and stops execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach is used to stop execution of the program in case of critical errors that are not related to business flow of the program.&lt;/p&gt;
&lt;h4&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Easy to stop an execution of the program.&lt;/li&gt;
&lt;li&gt;Guarantees that the program will not continue execution in case of critical errors.&lt;/li&gt;
&lt;li&gt;Application will stop very fast.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Since the program stops execution with a code, it is hard to debug without logs.&lt;/li&gt;
&lt;li&gt;The program stops execution, that is not what we usually want.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Panic and recover in Go&lt;/h2&gt;
&lt;p&gt;We went through different ways to handle errors in the program. We have successfully reviewed the flows and pros and cons of each approach.
During the review we also mentioned that &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; supports all of them, but it’s important to jump a little bit deeper into it.&lt;/p&gt;
&lt;h3&gt;Error type in Go&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; has a special interface to represent an error. It is called &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; and it is defined in the &lt;a href=&quot;https://golang.org/pkg/builtin/#error&quot;&gt;builtin package&lt;/a&gt;.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;	Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use this interface to define our own error types and to use them in our programs.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// NewMyError factory method that creates a new MyError.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; NewMyError&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;MyError&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; MyError&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  message&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;e &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;MyError&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;message&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; type is expected to be the latest return value of a function.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; func1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; NewMyError&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;error message&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; func2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() (&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;NewMyError&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;error message&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we also expect that the caller will check the error and handle it. There is a popular linter that checks it for us: &lt;a href=&quot;https://github.com/kisielk/errcheck&quot;&gt;errcheck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, errors can be stacked in a chain, wuth two interfaces:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  Unwrap&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  Unwrap&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;a href=&quot;https://pkg.go.dev/errors&quot;&gt;errors&lt;/a&gt; package that contains useful helpers to work with errors.&lt;/p&gt;
&lt;p&gt;Errors is the main way to handle errors in &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; and it is used in most of the cases and suggested to be used when possible.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Note: If you can use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; type, use it. Do not even thing to use any other error handling approaches.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Panic and recover&lt;/h3&gt;
&lt;p&gt;We went through &lt;em&gt;throw error&lt;/em&gt; handling flow. Although exceptions are very popular in other languages, &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; does not support them.
In &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; we have &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;recover&lt;/code&gt; functions that are used to handle critical errors.&lt;/p&gt;
&lt;p&gt;The code that uses &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; usually means that something went wrong, very wrong.
When we throw &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; we stop execution of current code and start to unwind the stack of the program, with no call stack code execution.
But all defers are still executed, even for functions that are not expecting to handle panics.
We will see it in the following example.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	defer&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Defer main&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) }()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Hello world&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;	func1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Not executed code main&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; func1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	defer&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Defer func1&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) }()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;	func2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Not executed code func1&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; func2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	defer&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Defer func2&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) }()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;	panic&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Test panic&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Not executed code func2&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Output:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Hello world&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Defer func2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Defer func1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Defer main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// panic: Test panic&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// goroutine 1 [running]:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// main.func2()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 	/tmp/sandbox493636343/prog.go:26 +0x49&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// main.func1()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 	/tmp/sandbox493636343/prog.go:19 +0x3f&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// main.main()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 	/tmp/sandbox493636343/prog.go:11 +0x7d&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Program exited.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we are using &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; in &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt; function, we stop execution of the program and start to unwind the stack. All &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;defer&lt;/code&gt;s are executed from &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func2&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;func1&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;main&lt;/code&gt;. Because we have not &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;recover&lt;/code&gt;ed from the panic, the program stops execution and prints a panic message with stack trace.&lt;/p&gt;
&lt;p&gt;We can use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;recover&lt;/code&gt; to handle panics and sometimes we will, but as good practice let’s agree that we will not use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt;s as a control flow of the program.&lt;/p&gt;
&lt;h3&gt;Stop execution&lt;/h3&gt;
&lt;p&gt;Sometomes we want to just stop execution of the program. For example, we have a program that is a CLI tool and we want to stop execution of the program if the user provided wrong parameters.&lt;/p&gt;
&lt;p&gt;We can use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;os.Exit&lt;/code&gt; to stop execution of the program.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;os&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; len&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;os&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Args&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Please provide a name&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    os&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Exit&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Hello&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;os&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Args&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// &gt; ./main test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Hello test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// &gt; ./main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Please provide a name&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// exit status 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;os.Exit&lt;/code&gt; will close program emidiately and will not execute any &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;defer&lt;/code&gt;s. This way is even more dangerous than &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; and should be used only in cases when we know what do we do.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Note: Do not use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;os.Exit&lt;/code&gt; unless you know what you are doing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Panic in libraries&lt;/h2&gt;
&lt;p&gt;Finally, let’s talk about panics in libraries. We have already mentioned that we should not use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; as a control flow of the program.
But, why are libraries so unique?&lt;/p&gt;
&lt;p&gt;Libraries are created to be used by other programs and people.
When people use libraries, they expect that the library will not stop execution of the program.
If there are any errors, library will return an error and the caller will know about it based on the interface and can handle it.&lt;/p&gt;
&lt;p&gt;This approach helps to be sure that even without careful reading of the documentation, the caller will not be surprised by the behavior of the library. And it is a good practice to follow.
Error handling through return value helps to be &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; code more predictable and stable. This simple rule helps to make programs to be unfailable on production.&lt;/p&gt;
&lt;h3&gt;One exception and informal agreement&lt;/h3&gt;
&lt;p&gt;Although we have a rule that we should not use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; in libraries, there is one exception.
Sometimes libraries return &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; value and we know that caller in the most cases will not handle it and just panic.&lt;/p&gt;
&lt;p&gt;There are some examples:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;regexp.Compile&lt;/code&gt; - it is expected that the caller will provide a valid regular expression.
&lt;ul&gt;
&lt;li&gt;If the regexp is set in constant code &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;regexp.Compile(&quot;invalid regexp&quot;)&lt;/code&gt;, we will just panic and fix the code.&lt;/li&gt;
&lt;li&gt;If the regexp is provided as an input from the user, we should handle the error ro notify user and move forward with execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;uuid.NewRandom&lt;/code&gt; (&lt;a href=&quot;https://github.com/google/uuid/blob/655bf50db9d265813a26b0fe2a5d1e80fb9e3c6b/version4.go#L13-L15&quot;&gt;source code&lt;/a&gt;)
Where we create a random UUID generator. If we have a problem with the random generator, it will return an error.
&lt;ul&gt;
&lt;li&gt;In the most cases we will panic, because we expect that random generator will work.&lt;/li&gt;
&lt;li&gt;In some cases we will handle the error and use some fallback generator (for example from an external service).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you can see, there are some cases when we expect from the caller to panic in the most cases of using a library.
We &lt;strong&gt;ALWAYS&lt;/strong&gt; provide the interface with &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; returned as a value, but since we know that in the most cases the caller will not handle the error, we can provide a &lt;em&gt;helper&lt;/em&gt; function that will panic in case of error.&lt;/p&gt;
&lt;p&gt;Let’s see an example:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Will return &quot;test&quot;.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))         &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Will return the error.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;MustCompile&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Will return &quot;test&quot;.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;MustCompile&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Will panic&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; Compile&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;regexp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; regexp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;New&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;critical error, empty regexp&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; regexp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; MustCompile&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;regexp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	res&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; Compile&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;regexp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;		panic&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; res&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Output:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// test &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;//  critical error, empty regexp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// panic: critical error, empty regexp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// goroutine 1 [running]:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// main.MustCompile(...)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 	/tmp/sandbox2091129551/prog.go:26&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// main.main()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 	/tmp/sandbox2091129551/prog.go:12 +0x178&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Program exited.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a good practice or/and agreement that if we have a helper-function that throws a panic, we should name it with &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Must&lt;/code&gt; prefix. For example: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;MustCompile&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;MustNew&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;MustOpen&lt;/code&gt; and so on.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Note: Do not use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;panic&lt;/code&gt; in libraries except you provide a helper function with &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Must&lt;/code&gt; prefix.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt; we have all tools to handle errors. But the preferrable way to use errors is to return them as a value and handle them in the caller code.&lt;/p&gt;
&lt;p&gt;If a developer of a library expects that in the most cases the caller will not handle the error, they can provide a helper function with &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Must&lt;/code&gt; prefix that will panic in case of error. But the main interface of the library &lt;strong&gt;MUST&lt;/strong&gt; still return an error.&lt;/p&gt;
&lt;p&gt;Let’s follow good practices and make our code more stable and predictable.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In computer programming, an entry point is the place in a program where the execution of a program begins, and where the program has access to command line arguments. &lt;a href=&quot;https://safigo.dev/posts/2023-07-31-go-panic-libraries/#user-content-fnref-entry_point&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>panic</category><category>error-handling</category></item><item><title>Multiple mastodon aliases to domain using Cloudflare Pages</title><link>https://safigo.dev/posts/2023-07-08-mastodon-alias-in-cloudflare/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-07-08-mastodon-alias-in-cloudflare/</guid><description>Step-by-step guide on associating multiple mastodon account aliases to a domain with Cloudflare Pages, eliminating the need for workers or extra coding</description><pubDate>Sun, 09 Jul 2023 05:14:23 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Recently, I’ve begun utilizing &lt;a href=&quot;https://joinmastodon.org/&quot;&gt;Mastodon&lt;/a&gt; as my go-to social media platform for technical queries. I’ve found that while Mastodon’s decentralized nature – a core aspect of the Fediverse – is attractive, it also brings about some complexities. Similar to how email addresses work, a user’s profile on Mastodon is tied to their instance’s domain.&lt;/p&gt;
&lt;p&gt;In my journey, I discovered &lt;a href=&quot;https://fosstodon.org/&quot;&gt;Fosstodon&lt;/a&gt;, a server with a community that aligns with my perspectives. I wished to tie my &lt;a href=&quot;https://fosstodon.org/&quot;&gt;Fosstodon&lt;/a&gt;’s account to my personal domain and username, essentially making it &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;me@aohorodnyk.com&lt;/code&gt;. For my website, I use the superb Hugo static site generator and deploy it to CloudFlare Pages, but it doesn’t have any server-side logic to resolve the name.
Following, this goal came with a challenge: I had to find a solution without any server-side logic to resolve the name.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;I came across a service named &lt;a href=&quot;https://webfinger.net/&quot;&gt;WebFinger&lt;/a&gt; in my search for a solution. &lt;a href=&quot;https://webfinger.net/&quot;&gt;WebFinger&lt;/a&gt; utilizes the fediverse specification to resolve names. When I input my &lt;a href=&quot;https://fosstodon.org/&quot;&gt;Fosstodon&lt;/a&gt;’s account &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;aohorodnyk@fosstodon.org&lt;/code&gt; into a search field, it demonstrates how the name gets resolved.&lt;/p&gt;
&lt;p&gt;It does these two things:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;04:15:24 Looking up WebFinger data for acct:aohorodnyk@fosstodon.org&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;04:15:24 GET https://fosstodon.org/.well-known/webfinger?resource=acct%3Aaohorodnyk%40fosstodon.org&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From my analysis, I concluded that for an alias to my &lt;a href=&quot;https://fosstodon.org/&quot;&gt;Fosstodon&lt;/a&gt;’s account, the same JSON should be resolved by this path: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger?resource=acct%3Ame%40aohorodnyk.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The simplest approach would be to create a file /.well-known/webfinger with the content from &lt;a href=&quot;https://fosstodon.org/&quot;&gt;Fosstodon&lt;/a&gt;. The downside is that all users in my domain would be resolved with the same account. So, I needed to find a way to resolve different files by different GET parameters to the same path.&lt;/p&gt;
&lt;h2&gt;The solution&lt;/h2&gt;
&lt;p&gt;My search for a way to apply minimal logic to resolve different files by different GET parameters to the same path was initially fruitless. The only available solutions online involved using &lt;a href=&quot;https://developers.cloudflare.com/pages/platform/functions/&quot;&gt;CloudFlare Workers/CloudFlare Functions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Reluctantly, I was considering using functions. However, the unpredictable pricing of serverless solutions was a deterrent. I didn’t want to incur costs for my minimalist needs.&lt;/p&gt;
&lt;p&gt;After several failed attempts, including trying to create a file with the full name &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger?resource=acct%3Ame%40aohorodnyk.com&lt;/code&gt;, I found a ray of hope in &lt;a href=&quot;https://developers.cloudflare.com/rules/transform/&quot;&gt;CloudFlare Transform Rules&lt;/a&gt;. This feature lets us create rules to transform requests to our server.&lt;/p&gt;
&lt;h3&gt;CloudFlare Transform Rules&lt;/h3&gt;
&lt;p&gt;The concept was to develop a rule that could parse &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger?resource=acct%3Ame%40aohorodnyk.com&lt;/code&gt; and transform it into a unique file in CloudFlare Pages. The main file &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger&lt;/code&gt; wouldn’t exist at all, ensuring all other requests returned a 404 as expected.&lt;/p&gt;
&lt;h4&gt;Rule Requirements&lt;/h4&gt;
&lt;p&gt;While it might not be overly critical, it’s beneficial to lay down requirements for our solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The request &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger?resource=acct%3Ame%40aohorodnyk.com&lt;/code&gt; must resolve our JSON&lt;/li&gt;
&lt;li&gt;The same JSON should be resolved on the request &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger?resource=acct%3Ame%40aohorodnyk.com&amp;#x26;format=json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For ALL other requests, a 404 error should be returned&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Successful Implementation&lt;/h4&gt;
&lt;p&gt;In CloudFlare’s admin page, I formulated a rule with specific settings and the action to transform the request to the file &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger-aohorodnyk.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Expression preview: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;(http.request.uri.path eq &quot;/.well-known/webfinger&quot; and http.request.uri.query contains &quot;resource=acct:me@aohorodnyk.com&quot;) or (http.request.uri.path eq &quot;/.well-known/webfinger&quot; and http.request.uri.query eq &quot;resource=acct%3Ame%40aohorodnyk.com&quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Working rules&quot; width=&quot;2108&quot; height=&quot;1302&quot; src=&quot;https://safigo.dev/_astro/2023-07-08-mastodon-alias-in-cloudflare-diagrams-transform-rules.DMB3aE2W_1Ehoc9.webp&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;And the action is to transform the request to the file &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/.well-known/webfinger-aohorodnyk.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Transformation rules&quot; width=&quot;1528&quot; height=&quot;932&quot; src=&quot;https://safigo.dev/_astro/2023-07-08-mastodon-alias-in-cloudflare-diagrams-rewrite-parameters.Y9FghpEb_ehWSy.webp&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Evaluation&lt;/h2&gt;
&lt;p&gt;Upon saving the rules, I ran various positive and negative test cases using &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;curlie&lt;/code&gt; and found the results to be successful:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;# Positive test cases&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; curlie&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/.well-known/webfinger?resource=acct%3Ame%40aohorodnyk.com&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HTTP/2&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 200&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; curlie&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/.well-known/webfinger?resource=acct:me@aohorodnyk.com&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HTTP/2&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 200&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;# Negative test cases&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; curlie&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/.well-known/webfinger?resource=acct%3Aame%40aohorodnyk.com&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; # wrong username with prefix `a`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HTTP/2&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 404&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; curlie&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/.well-known/webfinger?resource=acct%3Amea%40aohorodnyk.com&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; # wrong username with suffix `a`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HTTP/2&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 404&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; curlie&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/.well-known/webfinger?resource=acct%3Ame%40ohorodnyk.com&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; # wrong domain&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HTTP/2&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 404&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; curlie&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/.well-known/webfinger?resource=acct%3Ame%40aohorodnyk.co&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; # wrong domain&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HTTP/2&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 404&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Overall, the solution proved to be straightforward, efficient, cost-free, and operational. Moreover, it demonstrated excellent scalability for multiple users on the same domain.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>mastodon</category><category>cloudflare</category><category>cloudflare-pages</category></item><item><title>Effortless Node.js Version Management with the Fish Shell</title><link>https://safigo.dev/posts/2023-06-10-fish-nvm/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-06-10-fish-nvm/</guid><description>Discover an easy-to-implement method to merge Node.js version management (nvm) and the Fish shell for an improved user experience.</description><pubDate>Sat, 10 Jun 2023 22:00:53 GMT</pubDate><content:encoded>&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Continuing our exploration of the &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt; and its synergy with prevalent tools, this post follows the &lt;a href=&quot;https://safigo.dev/posts/2023-06-10-fish-autovenv/&quot;&gt;prior piece&lt;/a&gt; focused on &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;’s &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This write-up provides a straightforward strategy to incorporate automatic &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; version control with the &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;, whilst avoiding resource-hungry frameworks like &lt;a href=&quot;https://github.com/oh-my-fish/oh-my-fish&quot;&gt;oh-my-fish&lt;/a&gt; which can often slow down the shell.&lt;/p&gt;
&lt;h2&gt;A Brief on Node.js Version Management (nvm)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; is a widely embraced JavaScript runtime environment, enabling the execution of JavaScript code outside a browser. It finds utility in the creation of server-side apps, command-line tools, and even desktop and mobile apps.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt;, renowned for managing multiple &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; versions on a single machine, facilitates easy installation and swapping between different Node.js versions with a single command.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt;, while built for &lt;a href=&quot;https://www.gnu.org/software/bash/&quot;&gt;Bash&lt;/a&gt; and &lt;a href=&quot;https://www.zsh.org/&quot;&gt;Zsh&lt;/a&gt; shells, isn’t directly compatible with the &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;. There are several ways to mesh &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt; with the &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;, but they are often too intricate or resource-consuming.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;In my experience, attempting to use an NVM clone in &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt; fell short of my expectations. It failed to accomplish the primary task of automatically shifting between &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; versions when I switch the directory based on the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;.nvmrc&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;The Method&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;The goal is to have &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; versions switch automatically when the directory is changed, based on the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;.nvmrc&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Why not use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;.node-version&lt;/code&gt;? The &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;.nvmrc&lt;/code&gt; file is favored due to its support for additional options like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;iojs&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;lts/*&lt;/code&gt;, plus being a standard for &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;The How&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/safigo/fish-nvm&quot;&gt;implementation&lt;/a&gt; is uncomplicated as usual. It doesn’t entail multiple dependencies or complex logic. It’s essentially a few lines of code that get the job done.&lt;/p&gt;
&lt;h3&gt;Setting It Up&lt;/h3&gt;
&lt;p&gt;The plugin is dependent on another plugin &lt;a href=&quot;https://github.com/edc/bass&quot;&gt;edc/bass&lt;/a&gt;, which is a utility for executing Bash commands from &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;. It’s a simple plugin that can be installed through &lt;a href=&quot;https://github.com/jorgebucaran/fisher&quot;&gt;fisher&lt;/a&gt; or manually.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;fish&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;fisher&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; install edc/bass&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I suggest using &lt;a href=&quot;https://github.com/jorgebucaran/fisher&quot;&gt;fisher&lt;/a&gt; as a simplistic plugin manager for Fish. I’ve authored a plugin that can be easily installed through &lt;a href=&quot;https://github.com/jorgebucaran/fisher&quot;&gt;fisher&lt;/a&gt; and amalgamated into any Fish environment. Should you have reasons not to use Fisher, simply copy-paste &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;nvm.fish&lt;/code&gt; files from all directories to your &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;~/.config/fish/&lt;/code&gt; in their respective ones.&lt;/p&gt;
&lt;p&gt;To set up the plugin with &lt;a href=&quot;https://github.com/jorgebucaran/fisher&quot;&gt;fisher&lt;/a&gt;, execute the following command:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;fish&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;fisher&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; install aohorodnyk/fish-nvm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;How to Use&lt;/h3&gt;
&lt;p&gt;Upon changing the directory based on the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;.nvmrc&lt;/code&gt; file, the plugin will automatically switch between &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; versions. If the required version of &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; isn’t installed, it will be installed automatically.&lt;/p&gt;
&lt;h4&gt;Configurations&lt;/h4&gt;
&lt;p&gt;No particular configurations are required for this plugin. However, you can configure it by setting the below environment variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;nvmrc_enable&lt;/code&gt; (default: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;yes&lt;/code&gt;): Toggles Fish NVM on or off. Set to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;no&lt;/code&gt; to disable.&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;nvmrc_announce&lt;/code&gt; (default: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;yes&lt;/code&gt;): Toggles on or off the announcement of the Node.js version change. Set to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;no&lt;/code&gt; to disable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;Don’t hesitate to utilize the &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;. It’s a fast, versatile, and user-friendly shell that stands as a strong contender to bash and zsh.&lt;/p&gt;
&lt;p&gt;Contributing to open-source is a great way to learn, assist others, and help make the technological world simpler and better for all.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>fish-shell</category><category>nodejs</category><category>nvm</category></item><item><title>Integrating Python&apos;s Virtualenv with Fish shell without overcomplicated frameworks</title><link>https://safigo.dev/posts/2023-06-10-fish-autovenv/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-06-10-fish-autovenv/</guid><description>This blog offers a solution to seamlessly integrate Python&apos;s virtualenv with the Fish shell, enhancing its user experience and productivity.</description><pubDate>Sat, 10 Jun 2023 20:12:16 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt; is renowned for its user-friendly nature, making it an ideal command-line interface for macOS, Linux, and more. The shell stands out with its unique features, including auto-completion, syntax highlighting, and tabbed completion. Additionally, its learning curve is gentle enough for beginners to grasp quickly.&lt;/p&gt;
&lt;p&gt;Despite these attractive attributes, many developers I’ve come across don’t prefer &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;, primarily due to integration gaps with tools like &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;’s &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt;. So, in this article, I’m offering a simple solution for automatic &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt; activation for &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;, steering clear of resource-intensive frameworks like &lt;a href=&quot;https://github.com/oh-my-fish/oh-my-fish&quot;&gt;oh-my-fish&lt;/a&gt; that often slow down the shell.&lt;/p&gt;
&lt;h2&gt;Understanding Python’s Virtualenv&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;’s &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt; is a tool that creates isolated &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt; environments, making it an invaluable resource for managing project dependencies and testing &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;’s new versions without affecting the system’s main installation.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;It is perplexing and perhaps not ideal to have &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;’s dependencies installed globally instead of project-specific folders. This issue necessitates workarounds such as &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;The Objective&lt;/h2&gt;
&lt;p&gt;Before diving into the solution, let’s clearly define our goal.&lt;/p&gt;
&lt;h3&gt;Task&lt;/h3&gt;
&lt;p&gt;We aim to automate the activation of &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt; when we navigate into the project folder or any of its sub-folders. Additionally, we want to deactivate &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt; when exiting the project’s scope.&lt;/p&gt;
&lt;p&gt;A bottom-up search for the &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt; folder is crucial as multiple &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt;s can reside within the project folder, and we need to use the nearest one.&lt;/p&gt;
&lt;p&gt;The ultimate goal is to devise a minimalist solution to minimize performance hindrances and ensure maximum compatibility with any Fish environment.&lt;/p&gt;
&lt;h3&gt;Solution: An Adapted Plugin&lt;/h3&gt;
&lt;p&gt;I adapted the code from &lt;a href=&quot;https://github.com/timothybrown/fish-autovenv&quot;&gt;timothybrown/fish-autovenv&lt;/a&gt;, originally created by &lt;a href=&quot;https://github.com/timothybrown&quot;&gt;Timothy Brown&lt;/a&gt;, and published the modified version on GitHub.&lt;/p&gt;
&lt;p&gt;The existing solution had a few shortcomings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It was incompatible with newer versions of Fish, and my goal was to retain simplicity.&lt;/li&gt;
&lt;li&gt;The plugin for created for &lt;a href=&quot;https://github.com/oh-my-fish/oh-my-fish&quot;&gt;oh-my-fish&lt;/a&gt;, which is a resource-intensive framework that slows down the shell.&lt;/li&gt;
&lt;li&gt;The plugin could only detect virtual environments in the current directory, not in specified sub-directories. For instance, I store my virtual environments in a .venv sub-directory.&lt;/li&gt;
&lt;li&gt;The plugin didn’t apply the virtual environment when opening a terminal in a directory containing a custom virtual environment.&lt;/li&gt;
&lt;li&gt;It searched for &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt;s top-down (&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/home&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/home/user&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/home/user/projects&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;/home/user/projects/pytest&lt;/code&gt;), whereas a bottom-up approach would have been more efficient and user-friendly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a minimalist plugin manager for Fish, I recommend &lt;a href=&quot;https://github.com/jorgebucaran/fisher&quot;&gt;fisher&lt;/a&gt;. I’ve created a plugin that can be installed via &lt;a href=&quot;https://github.com/jorgebucaran/fisher&quot;&gt;fisher&lt;/a&gt; and integrated into any Fish environment. If there are any reasons why you don’t want to use Fisher, you can just copy-paste &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;conf.d/autoenv.fish&lt;/code&gt; file to your &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;~/.config/fish/conf.d&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;The project can be found here: &lt;a href=&quot;https://github.com/safigo/fish-autovenv&quot;&gt;aohorodnyk/fish-autovenv&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;To install &lt;a href=&quot;https://github.com/safigo/fish-autovenv&quot;&gt;aohorodnyk/fish-autovenv&lt;/a&gt;, by using &lt;a href=&quot;https://github.com/jorgebucaran/fisher&quot;&gt;fisher&lt;/a&gt;:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;fish&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;fisher&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; install aohorodnyk/fish-autovenv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The plugin offers several configurable settings for a tailored user experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;set -U autovenv_enable yes|no&lt;/code&gt; - to enable or disable the plugin (enabled by default).&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;set -U autovenv_announce yes|no&lt;/code&gt; - to enable or disable announcements when &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt; is activated or deactivated (enabled by default).&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;set -U autovenv_dir &apos;.venv&apos;&lt;/code&gt; - to specify the name of the directory where &lt;a href=&quot;https://virtualenv.pypa.io/&quot;&gt;virtualenv&lt;/a&gt; is located (default is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;.venv&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Don’t be apprehensive about using the &lt;a href=&quot;https://fishshell.com/&quot;&gt;Fish shell&lt;/a&gt;. It’s a versatile, fast, and intuitive shell, making it a worthy alternative to bash and zsh.&lt;/p&gt;
&lt;p&gt;Contributing to open-source is an excellent way to learn, help others, and contribute to making the technological world better and simpler for everyone.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>fish-shell</category><category>python</category><category>virtualenv</category></item><item><title>Dart should not be ignored</title><link>https://safigo.dev/posts/2023-06-08-dart-should-not-be-ignored/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-06-08-dart-should-not-be-ignored/</guid><description>Why dart is a good language and why you should take a look at it?</description><pubDate>Fri, 09 Jun 2023 05:32:23 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Introduced in 2011, Dart is a modern language developed by Google, designed for crafting web, server, and mobile applications. As a general-purpose language, Dart is versatile and flexible, supporting a wide array of developments. It’s a statically typed, garbage-collected language which combines object-oriented and functional programming paradigms. Dart can be compiled to JavaScript and it presents a user-friendly C-style syntax, making it relatively straightforward to learn and apply.&lt;/p&gt;
&lt;p&gt;However, despite these features, Dart is not the favored language among the developers I encounter, and positive feedback is quite scarce. Personally, my preference leans towards Go, but I acknowledge Dart has certain distinctive elements we can glean insights from. Let’s explore some unique attributes.&lt;/p&gt;
&lt;h2&gt;Dart as a Statically Typed Language&lt;/h2&gt;
&lt;p&gt;Dart’s syntax closely resembles those of Java, C#, and Kotlin. This may be advantageous as these languages are widely recognized, although I confess I’m not particularly enamored with them.&lt;/p&gt;
&lt;p&gt;Dart, like many languages, has introduced a concise syntax for variable definition, and it seems to elevate this feature. Not only does it support conventional type declarations such as &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;var&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;final&lt;/code&gt;, and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;const&lt;/code&gt;, Dart also integrates unusual variable types for static languages like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;late&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;dynamic&lt;/code&gt;. This surprising blend of characteristics imparts Dart with a uniqueness that can broaden our understanding of varying concepts.&lt;/p&gt;
&lt;h2&gt;Mixins in Dart&lt;/h2&gt;
&lt;p&gt;I first encountered mixins in Ruby, a feature that although could complicate the understanding of the code, I recognized its potential. Mixins provide a means to incorporate new functionality into classes without necessitating inheritance, enhancing flexibility and promoting the object-oriented programming approach.&lt;/p&gt;
&lt;p&gt;Dart embraces mixins but in a more declarative way. When we need to use a function from a mixin, we must import the class’s extension. This enhances the readability and comprehension of the code, which is a commendable improvement.&lt;/p&gt;
&lt;h2&gt;Null Safety Feature&lt;/h2&gt;
&lt;p&gt;While null safety is not an innovative feature, being used in numerous languages, Dart has integrated it into its core. It feels inherently a part of the language, which is a refreshing experience.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The objective of this succinct article is to present a few key points aimed at fostering a less toxic environment in our world.&lt;/p&gt;
&lt;p&gt;To summarize, Dart may not be my go-to language, nor the most favored among my developer peers. However, its unique features like unusual static type declarations, an improved version of mixins, and native null safety are enlightening and can significantly contribute to our programming knowledge. Despite my preference for Go, I respect and appreciate the diverse learning opportunities Dart presents.&lt;/p&gt;
&lt;p&gt;I urge individuals not to despise any programming language, but instead contribute their knowledge and experimentation for its advancement. Dart may not be perfect, but its strengths make it too promising to be dismissed outright.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>dart</category><category>programming</category></item><item><title>Is Redis merely caching system?</title><link>https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/</guid><description>The article explains why Redis and Memcache should be considered as matured full-fledged databases, rather than just caching systems, and why this distinction is important for software engineers.</description><pubDate>Sat, 18 Mar 2023 04:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Improving the performance of distributed applications is a common task for backend software engineers, especially when multiple servers use a database to retrieve data and generate responses. Communication among engineers occurs frequently and often revolves around work-related topics and technology.&lt;/p&gt;
&lt;p&gt;Redis and Memcache are commonly referred to as caching systems or cache services, even by experienced individuals, but they should be recognized as full-fledged databases due to their maturity and functionality. This article will explore the reasons why it is important to recognize Redis and Memcache as databases.&lt;/p&gt;
&lt;h2&gt;Defintions&lt;/h2&gt;
&lt;p&gt;In order to review the topic, it is necessary to establish clear definitions.&lt;/p&gt;
&lt;h3&gt;Cache&lt;/h3&gt;
&lt;p&gt;In my understanding, cache refers to a software layer that stores precalculated results from previous computations, which can be utilized to avoid repeated calculations. Although some people view it as a quick storage solution, I believe this is debatable, as the primary objective of caching is to enhance performance by using a tool that provides adequate speed to achieve significant improvements.&lt;/p&gt;
&lt;p&gt;For instance, consider Full Page Cache&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fn-full_page_cache&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; as an example. Some websites may take a considerable amount of time&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fn-seconds_to_render&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; to load a page. To enhance performance, developers may include an extra table in MySQL&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fn-mysql&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, where they can save fully rendered pages. This strategy reduced the load time from 15 seconds to 100ms, which is a significant improvement that negates the need for high-speed storage solutions.&lt;/p&gt;
&lt;h4&gt;Cache definitions from Wiki and AI&lt;/h4&gt;
&lt;p&gt;There is a definition from &lt;a href=&quot;https://en.wikipedia.org/wiki/Cache_(computing)&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;In computing, a &lt;strong&gt;cache&lt;/strong&gt; (&lt;em&gt;/kæʃ/&lt;/em&gt; (listen) &lt;em&gt;KASH&lt;/em&gt;) is a hardware or software component that stores data so that future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation or a copy of data stored elsewhere. A cache hit occurs when the requested data can be found in a cache, while a cache miss occurs when it cannot. Cache hits are served by reading data from the cache, which is faster than recomputing a result or reading from a slower data store; thus, the more requests that can be served from the cache, the faster the system performs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And let’s follow trends and ask Chat-GPT what is cache.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;A cache is a temporary storage area that stores frequently accessed or recently accessed data, which helps to reduce the time it takes to access that data in the future. Caches can be found at various levels in a computer system, such as within a CPU, on a hard disk, or in a web browser. They function by keeping a copy of frequently used data or instructions closer to the processor or application, which decreases the time it takes to retrieve them from their original location. Caches can be hardware or software-based and can be designed to work with various types of data. By using a cache, a system can minimize the time it takes to retrieve data from slower storage devices or networks, leading to faster overall performance and a better user experience.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Database&lt;/h3&gt;
&lt;p&gt;A software program, known as a database&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fn-db_dbms&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; or a DBMS&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fn-db_dbms&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, is capable of storing data and allowing users to access it for reading and writing purposes through an API&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fn-db_api&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h4&gt;Database definitions from Wiki and AI&lt;/h4&gt;
&lt;p&gt;There is a definition from &lt;a href=&quot;https://en.wikipedia.org/wiki/Database&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;In computing, a &lt;strong&gt;database&lt;/strong&gt; is an organized collection of data stored and accessed electronically. Small databases can be stored on a file system, while large databases are hosted on computer clusters or cloud storage. The design of databases spans formal techniques and practical considerations, including data modeling, efficient data representation and storage, query languages, security and privacy of sensitive data, and distributed computing issues, including supporting concurrent access and fault tolerance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And let’s follow trends and ask Chat-GPT what is database.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;A database is a digital collection of organized data that is stored and accessed electronically. It is designed to efficiently store and manage large amounts of information. Typically, a database consists of one or more tables, each containing rows and columns of data. A row represents a single record, while each column represents a different attribute or field of the record. Databases have a wide range of applications, including business operations, scientific research, e-commerce, and social media. To create, modify, and query the data, specialized software called database management systems (DBMS) is used.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Redis and Memcache&lt;/h2&gt;
&lt;p&gt;As stated in our definitions, caching is a methodology rather than a particular service. This means that we have the flexibility to utilize any storage solution that suits our requirements in order to construct a cache. Whether it’s MySQL, MSSQL, MongoDB, Cassandra, CockroachDB, Redis, Memcached, or simply a hash map in memory within the application, the choice is not significant as long as it meets our needs and assists us in accomplishing our goals.&lt;/p&gt;
&lt;p&gt;Redis and Memcache are databases, as they are capable of storing data (primarily in memory) and offering an API for data access. Although they are limited to a predefined storage capacity, they may be suitable as the primary storage for our applications in specific scenarios that align with our requirements. In addition, Redis offers a range of features beyond storage, making it useful for a wide range of tasks.&lt;/p&gt;
&lt;h2&gt;Imprortance of naming&lt;/h2&gt;
&lt;p&gt;Although it may seem that naming is not crucial and we can assign any name we desire, using inaccurate names and definitions for tools may often create biases in our minds.&lt;/p&gt;
&lt;p&gt;By enhancing our understanding and naming conventions for various technologies, we can eliminate biases from our perspective, leading to more efficient problem-solving.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In conclusion, it is crucial to communicate more and ask questions when in doubt. Reading documentation and technical resources can also be helpful in gaining a better understanding of a topic. By doing so, we can avoid biases that can complicate our lives. It’s essential to create a culture where asking questions is encouraged, and everyone feels comfortable enough to seek clarity. In this way, we can increase our knowledge, improve our work, and work towards a more inclusive and unbiased environment. So, let’s be curious and open to learning, and not let biases hinder our progress.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Full page cache is a technique when full rendered response of some service (event full website page) are saved after the first render to not rerender it for every request. &lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fnref-full_page_cache&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I’ve seen websites that spent more than 15 seconds to render a page. &lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fnref-seconds_to_render&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MySQL is an open-source relational database management system. Link to &lt;a href=&quot;https://en.wikipedia.org/wiki/MySQL&quot;&gt;Wikipedia&lt;/a&gt;. &lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fnref-mysql&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Within our topic database, there is a DBMS (Database Management System) present. However, since the term “database” is too granular and not relevant to the user experience aspect, it is not of our interest. &lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fnref-db_dbms&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fnref-db_dbms-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When we speak about DB API we mean any interface that can be used to access data, like Golang interfaces, Java interfaces, SQL, CQL, MQL, etc. &lt;a href=&quot;https://safigo.dev/posts/2023-03-17-redis-memcache-caching-systems/#user-content-fnref-db_api&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>redis</category><category>caching</category><category>database</category></item><item><title>First release of gotimeparser</title><link>https://safigo.dev/posts/2023-03-06-gotimeparser-first-release/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-03-06-gotimeparser-first-release/</guid><description>Open Source is important for future of software development. I am happy to announce GoTimeParser&apos;s first release.</description><pubDate>Tue, 07 Mar 2023 06:34:35 GMT</pubDate><content:encoded>&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Many companies use service to service integration through different API porotocols.
I had the same situation in my production environment. At some point, clients of my service started to send me dates in different formats.&lt;/p&gt;
&lt;p&gt;Some of them sent timestamps in int, some of them used ISO 8601, etc. But what was clear, these dates were valid and we could not request to change it in one day.&lt;/p&gt;
&lt;p&gt;As a result of this issue, I implemented some solution that solved the issue and wrote a couple of articles that shared the issue and the approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2022-05-06-parse-timestamp/&quot;&gt;Parse timestamp formats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2022-05-07-parse-time-strings/&quot;&gt;Parse time from different non timestamp formats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2022-05-08-universal-time-unmarshaljson/&quot;&gt;Universal time UnmarshalJSON implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But I did not want to create an Open Source package, because of I believe that Open Source cannot be just few lines of code. It’s a right formatting of the code, some code coverage by tests, examples and the most important - is commitment to support it.&lt;/p&gt;
&lt;h2&gt;First release&lt;/h2&gt;
&lt;p&gt;Today is a day when I decided to invest time and commit to a simplification of software development in Go.
Time parsing is a regular issue, especially in event-driven architecture and microservice arachitectures.&lt;/p&gt;
&lt;p&gt;Feel free to use the zero-dependency library to solve all the main issues you could have with time parsing in Go.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>opensource</category><category>library</category></item><item><title>Preallocate dynamic structures</title><link>https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/</guid><description>Some dynamic structures can and should be preallocated</description><pubDate>Sat, 04 Mar 2023 03:30:35 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;We live in a beautiful software development time, where every language contains dynamic structures. Therefore, we can think about only some memory allocation.
Differences between development performance are significantly decreasing between statically and dynamically typed languages.&lt;/p&gt;
&lt;p&gt;We can write code on Go, Kotlin, Java, etc., almost like we write on statically typed languages like Python, JavaScript, PHP, etc. Of course, it’s impressive, but let’s discuss some things that can help us improve performance in a small, easy step.&lt;/p&gt;
&lt;p&gt;This short article will explain why preallocation is beneficial, even for dynamic structures.&lt;/p&gt;
&lt;h2&gt;Simplification in statically typed languages&lt;/h2&gt;
&lt;p&gt;The significant difference between statically typed languages and dynamically typed languages is mainly based on three main differences:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Memory management&lt;/li&gt;
&lt;li&gt;Verbosity&lt;/li&gt;
&lt;li&gt;Type conversion&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Verbosity and type conversion parts will discuss in future articles. However, memory management is the topic we will discuss right now.&lt;/p&gt;
&lt;h3&gt;Memory management&lt;/h3&gt;
&lt;p&gt;When dynamic languages were involved, all static languages required co-manage memory manually. Every developer had to consider an array size, resizing, memory cleaning, etc.&lt;/p&gt;
&lt;p&gt;Currently, every language (including C++) provides a way how to almost or entirely avoid memory management in these ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reference counters&lt;/li&gt;
&lt;li&gt;Garbage collectors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, if we are doing right, we can use some &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;slice&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fn-slice&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;ArrayList&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;vector&lt;/code&gt; (similar structures from different languages), etc., to work with dynamic arrays.
So, in the current world, we can append whatever amount of data we want to build a &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;slice&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fn-slice&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Example with an array:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	const&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; size&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	arr&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;arr&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// [0 0 0 0 0 0 0 0 0 0]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; size&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		arr&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 333&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;arr&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// [333 333 333 333 333 333 333 333 333 333]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above example shows that we had a fixed array size where we could not add the eleventh element without some manipulations.&lt;/p&gt;
&lt;p&gt;Example with a dynamic array data structure (&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;slice&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fn-slice&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; from Go):&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	const&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; size&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	arr&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;arr&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// []&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; size&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		arr&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; append&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;arr&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;333&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;arr&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// [333 333 333 333 333 333 333 333 333 333]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see, we created a slice with zero size. After that, we extended it from zero elements up to 10. After that, we had no issues adding one or hundreds of more pieces.&lt;/p&gt;
&lt;h2&gt;Performance improvements&lt;/h2&gt;
&lt;p&gt;As we saw above, dynamic structures like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;slice&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fn-slice&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; improve our life quality and help us write code comparably fast as on dynamic languages.&lt;/p&gt;
&lt;p&gt;The example above provided an example where we created a slice with zero size and allocated it up to ten elements. However, there is a minor performance issue here. However, we knew the expected size (in our use case, it was ten elements), so we could preallocate the slice and improve performance.&lt;/p&gt;
&lt;p&gt;Let’s create a small benchmark to see the difference between preallocated and non-allocated slices in Go:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; slices_test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; BenchmarkNonAllocated&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	slice&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// run the allocate variable b.N times&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		slice&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; append&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;333&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; BenchmarkPreAllocated&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	slice&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; make&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// run the allocate variable b.N times&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		slice&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; append&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;333&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running result:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; go&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; test&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; -benchmem&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; -bench&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; .&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; github.com/safigo/gox/slices&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; -benchtime=20s&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;goos:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; darwin&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;goarch:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; arm64&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;pkg:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; github.com/safigo/gox/slices&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;BenchmarkNonAllocated-8&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;         1000000000&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;              14.52&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; ns/op&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;           42&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; B/op&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;          0&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; allocs/op&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;BenchmarkPreAllocated-8&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;         1000000000&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;               3.918&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; ns/op&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;           8&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; B/op&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;          0&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; allocs/op&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;PASS&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt;      github.com/safigo/gox/slices&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt;        19.872s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the result, we can see that performance improvement is ~3.7 times.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This article needs to describe how slices, ArrayList, or similar data structures work. Then, it’s simple to find in your favorite search engine.&lt;/p&gt;
&lt;p&gt;Meanwhile, this article imperatively shows that preallocation significantly improves performance. In the article, we touched only &lt;em&gt;dynamic arrays&lt;/em&gt;, but it can be applied to every type like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;slice&lt;/code&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fn-slice&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;map&lt;/code&gt; (&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;hash map&lt;/code&gt;), etc.&lt;/p&gt;
&lt;p&gt;Our applications can handle millions of requests. So if we can improve performance for every request ONLY by this improvement, it will be a massive step for us.&lt;/p&gt;
&lt;p&gt;It’s a small part of the improvement. We will discuss other options in future articles as well.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Some high-level internals about slices can be &lt;a href=&quot;https://go.dev/blog/slices-intro&quot;&gt;read here&lt;/a&gt;. &lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fnref-slice&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fnref-slice-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fnref-slice-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-3&quot;&gt;↩&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fnref-slice-4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-4&quot;&gt;↩&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-03-03-preallocate-dynamic-structures/#user-content-fnref-slice-5&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-5&quot;&gt;↩&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>performance</category><category>optimization</category></item><item><title>Open questions about performance</title><link>https://safigo.dev/posts/2023-02-28-open-questions-about-performance/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-02-28-open-questions-about-performance/</guid><description>Introduction to basic questions about performance</description><pubDate>Wed, 01 Mar 2023 01:20:35 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;We live in a fantastic time with cheap resources and advanced chipsets in almost all devices. Moore’s law&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-moor_law&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; predicted a bright future with continued chip performance growth. This prediction offered us the future where we can meet our performance expectations by doing nothing in our code by making affordable investments in our hardware infrastructure.&lt;/p&gt;
&lt;p&gt;While this approach works well for most projects, after seeing tens or even hundreds of them, I can assume that these performance-neutral decisions postpone architectural complexity.&lt;/p&gt;
&lt;h2&gt;How do we measure performance?&lt;/h2&gt;
&lt;p&gt;When we speak about the performance of any application, we can mean many different parts that affect our business flow. The specific topic we can discuss will depend on the use case we want to review and the business problem(s) that solves our application. It could be any mix of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Network&lt;/li&gt;
&lt;li&gt;Memory (RAM&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-ram&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;)&lt;/li&gt;
&lt;li&gt;Disk&lt;/li&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a couple of examples of performance measurement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPU utilization per task&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-task&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Time execution per task&lt;/li&gt;
&lt;li&gt;Number of tasks executed per second&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-rps&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you measure &lt;strong&gt;CPU utilization per task&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-task&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/strong&gt;, this introductory article will likely not help you because you apply all possible optimizations. But we will focus on two other types of measurement.&lt;/p&gt;
&lt;h3&gt;Time execution per task&lt;/h3&gt;
&lt;p&gt;This is a straightforward way to measure the task.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We find a couple of paths in the task and identify payloads to trigger them.&lt;/li&gt;
&lt;li&gt;We trigger tasks by identified parameters.&lt;/li&gt;
&lt;li&gt;We calculate the execution time of our action (without transport time):
&lt;ul&gt;
&lt;li&gt;We can collect start and end times in nanoseconds (micro or milliseconds, depending on the performance of the task).&lt;/li&gt;
&lt;li&gt;We collect the difference somewhere.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Or we can calculate an execution time for an external spectator:
&lt;ul&gt;
&lt;li&gt;For example, we can run &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;curl&lt;/code&gt; with the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;time&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;When the function finishes, it will show us time calculations.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;________________________________________________________&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Executed&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1.01&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; secs&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; fish&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; external&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; usr&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1.18&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; millis&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0.16&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; millis&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1.02&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; millis&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; sys&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 4.25&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; millis&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1.88&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; millis&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 2.38&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; millis&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Number of tasks executed per second&lt;/h3&gt;
&lt;p&gt;We will not dive deep into this topic, but we must mention some tools to help you dive into the question.&lt;/p&gt;
&lt;p&gt;To calculate a number an RPS&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-rps&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; number, we can use one of the various available tools for that, like &lt;a href=&quot;https://k6.io&quot;&gt;k6&lt;/a&gt;, &lt;a href=&quot;https://jmeter.apache.org&quot;&gt;JMeter&lt;/a&gt;, &lt;a href=&quot;https://httpd.apache.org/docs/2.4/programs/ab.html&quot;&gt;Apache Bench (ab)&lt;/a&gt;, &lt;a href=&quot;https://github.com/JoeDog/siege&quot;&gt;Siege&lt;/a&gt;, etc.&lt;/p&gt;
&lt;p&gt;After running the chosen application with the required configuration, we will get a result with some numbers, like RPS, average request execution time, total time, number of performed requests, etc.&lt;/p&gt;
&lt;h3&gt;On-going metrics&lt;/h3&gt;
&lt;p&gt;It’s not a type of synthetic measurement but accurate data generated by real users.&lt;/p&gt;
&lt;p&gt;One of the most critical parts that barely related to the topic, but I couldn’t avoid it. Always collect at least high-level metrics for the real processing of your applications. Use public services or Open Source solutions, but always collect high-level metrics per endpoint.&lt;/p&gt;
&lt;p&gt;Ideally, we want to collect more detailed metrics for all incoming and outcoming IO&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-io&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2&gt;Why is it important to measure performance?&lt;/h2&gt;
&lt;p&gt;There are many reasons to know the performance of the application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Predict scaling hardware investments in case of glow&lt;/li&gt;
&lt;li&gt;Understand the limitations of an application&lt;/li&gt;
&lt;li&gt;Find the technical issues that could be reasons to leave your service customers
&lt;ul&gt;
&lt;li&gt;For example, response time is more than 1 second&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Find places for improvement to solve
&lt;ul&gt;
&lt;li&gt;Technical issues&lt;/li&gt;
&lt;li&gt;Scaling issues&lt;/li&gt;
&lt;li&gt;Save on hardware by decreasing the number of required resources&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Complex question&lt;/h2&gt;
&lt;p&gt;When we already have a system where we want to improve performance significantly, it requires:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deep understanding in performance analyzing: &lt;em&gt;collecting metrics&lt;/em&gt;, profiling an application, reviewing code, etc.&lt;/li&gt;
&lt;li&gt;Good knowledge of the product (good to have).&lt;/li&gt;
&lt;li&gt;Understanding of how to do refactoring with minimal effect on business processes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All applications sooner or later require these complicated steps due to the history of the application evolution. Usually, projects at this stage people name as &lt;em&gt;legacy&lt;/em&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fn-legacy&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;. Unfortunately, it’s the unavoidable result of every project.&lt;/p&gt;
&lt;p&gt;At the same time, we can keep writing more effective code to keep performance as good as possible to avoid premature performance issues.&lt;/p&gt;
&lt;h2&gt;The best practices&lt;/h2&gt;
&lt;p&gt;Following the best practices during everyday work could be challenging. But in reality, everything repeated many times will lead us to habits that we will apply without mental overwhelming.&lt;/p&gt;
&lt;p&gt;We will not speak here about the actual best practices because it’s a big question for a book or a couple of books. So, all these snippets and suggestions will be highlighted in the later articles.&lt;/p&gt;
&lt;p&gt;However, the basic knowledge of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Computer science&lt;/li&gt;
&lt;li&gt;Performance testing&lt;/li&gt;
&lt;li&gt;Code simplicity&lt;/li&gt;
&lt;li&gt;Benchmarking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It can help to postpone the tech debt. Follow the blog for the next articles for real snippets and examples.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This article was written as a reference for the following snippets and articles to avoid repetition.
It will be a good starting point for someone. And this article could be eventually updated to be more effective. Any feedback is welcome!&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Moore%27s_law&quot;&gt;Moore’s law&lt;/a&gt; is not a law. It’s an observation. And it looks like it has already stopped working. Anyway, it’s too important a part of the computer’s history to forget the name. &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-moor_law&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Random-access_memory&quot;&gt;RAM (Random-access memory)&lt;/a&gt; is a type of memory usually used to store temporary data related to currently running applications. &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-ram&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;By &lt;strong&gt;task&lt;/strong&gt;, I mean any work to be done in the scope of the process - for example, HTTP request processing, RabbitMQ message processing, cron-job scheduled tasks, etc. &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-task&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-task-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RPS or QPS (queries per second) - measurement where we calculate how many requests we can process per second in the given environment, like a node in the cloud, laptop, dedicated server, etc. &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-rps&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-rps-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Input/output&quot;&gt;IO - input/output&lt;/a&gt; is the communication between an information processing system. &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-io&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In this article &lt;strong&gt;legacy&lt;/strong&gt; word does not involve any negative connotations. It’s used here to highlight that project on the life-cycle stage where refactoring and improvements are required for future support and feature growth. &lt;a href=&quot;https://safigo.dev/posts/2023-02-28-open-questions-about-performance/#user-content-fnref-legacy&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 6&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>performance</category><category>engineering</category></item><item><title>Improving security in HTTPS communication</title><link>https://safigo.dev/posts/2023-02-17-https-certificate-validation/</link><guid isPermaLink="true">https://safigo.dev/posts/2023-02-17-https-certificate-validation/</guid><description>Make backend&lt;-&gt;backend integration through HTTPS is more secure by simple step</description><pubDate>Sat, 18 Feb 2023 06:40:42 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;We are living in a world where almost not left self-sufficient products.
Almost every product has at least one integration into other services.&lt;/p&gt;
&lt;p&gt;Different protocols can be used for communication between them, like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;REST&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;gRPC&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;GraphQL&lt;/code&gt;, etc.
However, all of them use some network-level protocol, and usually, as a network protocol, they use HTTP&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-http&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;HTTP&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-http&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; is a great multi-level&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-http_multi_level&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; communication protocol. It also provides secure options such as HTTP over SSL/TLS&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-https&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;This article will touch on some high-level concepts with links as starting points to read about them.
Something can be used with simplification to avoid detailed explanations, but provided links can be used to learn more details.
I will use &lt;a href=&quot;https://go.dev&quot;&gt;Golang&lt;/a&gt; as a great language for backend services.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;HTTPS pros and cons&lt;/h2&gt;
&lt;p&gt;HTTPS&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-https&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; provides good security that makes our internet safe and with a much better level of privacy.
Some details on how HTTPS’s security works can be found &lt;a href=&quot;https://www.cloudflare.com/learning/ssl/why-is-http-not-secure/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The protocol itself contains a couple of steps that help encryption in HTTPS be as secure as it is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/&quot;&gt;TLS handshake&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Certificate verification&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cloudflare.com/learning/ssl/why-is-http-not-secure/&quot;&gt;Encrypted communication&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will focus on step number two - Certificate Verification.&lt;/p&gt;
&lt;h3&gt;Certificate verification&lt;/h3&gt;
&lt;p&gt;Certificate verification is an important step that helps us to guarantee that we did a TLS handshake with a trusted actor without MITM&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-mitm&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; attack.&lt;/p&gt;
&lt;h4&gt;When the client finishes with a TLS handshake, it still has a question, is the opponents public key belongs to an expected actor?&lt;/h4&gt;
&lt;p&gt;It’s not a simple question. Security invented certificates for public keys&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-cert_public_key&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.
By having a trusted certificate&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-trusted_vertificate&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; we can sign the public key and verify that the certificate’s owner generated the public key.&lt;/p&gt;
&lt;h4&gt;But how to deliver a certificate, since it’s the same as a public key?&lt;/h4&gt;
&lt;p&gt;Public and private keys are secure parts, so we want to regenerate them as often as possible and keep the ability to reissue them, in case of potential compromises.&lt;/p&gt;
&lt;p&gt;On the other hand, certificates can be distributed to a limited amount of trusted issuers that will guarantee us the security and truthfulness of all signed keys. So, the decision was to build a database of public parts of root certificates&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-root_certificate&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;A list of trusted certificates (root certificates) is agreed upon across the organizations and companies&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-apple_list&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;. So they are delivered and updated from time to time. However, they are not updated so frequently, so companies and organizations can provide them to all customers in some acceptable gap during OS updates or browser updates.&lt;/p&gt;
&lt;h4&gt;The idea with the list of certificates looks fantastic. What could go wrong?&lt;/h4&gt;
&lt;p&gt;Root certificates authorities verified, and we can assume that we can trust them, but something can go wrong.
There are a couple of examples from &lt;a href=&quot;https://en.wikipedia.org/wiki/Root_certificate&quot;&gt;Wikipedia about Root Certificates&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DigiNotar hack of 2011 - In 2011, the Dutch certificate authority DigiNotar suffered a security breach.&lt;/li&gt;
&lt;li&gt;China Internet Network Information Center (CNNIC) Issuance of Fake Certificates.&lt;/li&gt;
&lt;li&gt;WoSign and StartCom: Issuing fake and backdating certificates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, we can add new simplified ways to get a certificate like Let’s Encrypt, AWS, Cloudflare, GCP, etc. I do not want to say they are not secure, but they simplified how we generate certificates.&lt;/p&gt;
&lt;p&gt;We can believe that one certificate issuer, like Cloudflare will generate exclusive certificates per domain because they can control certificates for how many domains they issue. Meanwhile, there is a small chance that a &lt;em&gt;hacker&lt;/em&gt; can generate the certificate for the same domain from another authority.&lt;/p&gt;
&lt;h2&gt;Specific root certificate verification&lt;/h2&gt;
&lt;p&gt;The initial goal was to secure our backend&amp;#x3C;-&gt;backend integration.
Let’s assume that we want to integrate with some financial institution’s API, where we will send some SPII&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fn-spii&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; data.&lt;/p&gt;
&lt;p&gt;There are a few agreements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We know that our API uses AWS.&lt;/li&gt;
&lt;li&gt;Also, we believe that AWS will not issue two certificates for the same domain for different accounts.&lt;/li&gt;
&lt;li&gt;We want to provide more guarantees than HTTPS for our customers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Based on everything we have discussed and reviewed, we can assume that the solution would be used strictly ONE root certificate that belongs to our partner’s provider. In our use case, it will be AWS.&lt;/p&gt;
&lt;h3&gt;Test system’s CA certificates&lt;/h3&gt;
&lt;p&gt;First of all, we need to test. Can we download a page, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;https://aohorodnyk.com/&lt;/code&gt;? It uses Cloudflare’s certificate.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		log&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Fatalln&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not read the URL with error: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Status code:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Status code: 200&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code above works well because it uses ALL system’s CA certificates.&lt;/p&gt;
&lt;p&gt;In the next test, let’s try to do the same for &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;https://aws.amazon.com/&lt;/code&gt;. We will use the system’s CA certificates as well.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aws.amazon.com/&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		log&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Fatalln&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not read the URL with error: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Status code:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Status code: 200&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Use only the AWS ROOT certificate&lt;/h3&gt;
&lt;p&gt;Before we will do that, we need to download the AmazonRootCA. For Amazon, it can be found in their &lt;a href=&quot;https://www.amazontrust.com/repository/AmazonRootCA1.pem&quot;&gt;repository&lt;/a&gt;, but for every website, it simply can be done through OpenSSL app or firefox.&lt;/p&gt;
&lt;p&gt;We downloaded Amazon’s certificate, and it’s content:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;plain&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-----BEGIN CERTIFICATE-----&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;rqXRfboQnoZsG4q5WTP468SQvvG5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-----END CERTIFICATE-----&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to modify the previous code that will ignore ALL system’s CA certs but only use our custom’s one.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;crypto/tls&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;crypto/x509&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// For the certificate, formatting is important. \n can be parsed as in the example, but&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// tabs or spaces that can be added before every line by IDE will break the cert.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	caCert&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;-----BEGIN CERTIFICATE-----&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;rqXRfboQnoZsG4q5WTP468SQvvG5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;-----END CERTIFICATE-----&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	rootCAs&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; x509&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;NewCertPool&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Create a new cert pool and ignore system&apos;s root certificates.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	ok&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; rootCAs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;AppendCertsFromPEM&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;caCert&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Add our custom CA cert.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		log&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Fatalln&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Cannot append our root certificate&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// This custom client is not for production use.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// For production, please, configure the client properly.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	httpClient&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Client&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		Transport&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Transport&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;			TLSClientConfig&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;tls&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Config&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;				RootCAs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rootCAs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Set custom root CAs.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;			},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; httpClient&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aws.amazon.com/&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		log&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Fatalln&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not read the URL with error: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Status code:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Status code: 200&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now, let’s try to fetch our domain &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;https://aohorodnyk.com/&lt;/code&gt; that uses Cloudflare’s certificate.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;crypto/tls&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;crypto/x509&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;	&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// For the certificate, formatting is important. \n can be parsed as in the example, but&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// tabs or spaces that can be added before every line by IDE will break the cert.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	caCert&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;-----BEGIN CERTIFICATE-----&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;rqXRfboQnoZsG4q5WTP468SQvvG5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;-----END CERTIFICATE-----&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	rootCAs&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; x509&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;NewCertPool&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Create a new cert pool and ignore system&apos;s root certificates.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	ok&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; rootCAs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;AppendCertsFromPEM&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;caCert&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Add our custom CA cert.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		log&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Fatalln&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Cannot append our root certificate&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// This custom client is not for production use.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;	// For production, please, configure the client properly.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	httpClient&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Client&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		Transport&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Transport&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;			TLSClientConfig&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;tls&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Config&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;				RootCAs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rootCAs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Set custom root CAs.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;			},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; httpClient&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;https://aohorodnyk.com/&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		log&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Fatalln&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Could not read the URL with error: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Could not read the URL with error: Get &quot;https://aohorodnyk.com/&quot;: x509: certificate signed by unknown authority.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Status code:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;resp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StatusCode&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If will change the domain to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;google.com&lt;/code&gt;, the error will be the same &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Could not read the URL with error: Get &quot;https://google.com/&quot;: x509: certificate signed by unknown authority&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Small steps can help us to improve the security of services. Most crucial is that these improvements do not require vast time investments. So, let’s make the web more secure!&lt;/p&gt;
&lt;p&gt;I hope this article will motivate people to pay attention to these small details.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP&quot;&gt;Hypertext Transfer Protocol (HTTP)&lt;/a&gt;. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-http&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-http-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;HTTP supports headers in requests and responses that help to keep an additional level of abstraction of internal protocols, for example &lt;a href=&quot;https://safigo.dev/posts/2021-07-03-mime-headers/&quot;&gt;Accept mime headers&lt;/a&gt;. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-http_multi_level&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/HTTPS&quot;&gt;HyperText Transfer Protocol Secure (HTTPS)&lt;/a&gt;. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-https&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-https-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3-2&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Man-in-the-middle_attack&quot;&gt;MITM (man-in-the-middle)&lt;/a&gt; is the type of attack where someone can read and/or change traffic transferred between two parties. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-mitm&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Certificate for public keys provides a way to verify that a specific private certificate signed public key. Details are &lt;a href=&quot;https://en.wikipedia.org/wiki/Public_key_certificate&quot;&gt;here&lt;/a&gt;. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-cert_public_key&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Public information is the same as a public key. It can be published anywhere without any risks to the owner. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-trusted_vertificate&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 6&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The first-level certificate is secured as best as possible and used only by an authority to sign domain certificates. Details are &lt;a href=&quot;https://en.wikipedia.org/wiki/Root_certificate&quot;&gt;here&lt;/a&gt;. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-root_certificate&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 7&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As an example, we can see the list of &lt;a href=&quot;https://support.apple.com/en-us/HT213080&quot;&gt;certificates trusted by Apple&lt;/a&gt; for all their products, like iOS, MacOS, TvOS, etc. Other organizations and companies can be simply found through your favorite search engine. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-apple_list&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 8&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.epa.gov/irmpoli8/protecting-sensitive-personally-identifiable-information-spii&quot;&gt;SPII (Sensitive Personally Identifiable Information)&lt;/a&gt; like credit card data, SSN, passport data, etc. &lt;a href=&quot;https://safigo.dev/posts/2023-02-17-https-certificate-validation/#user-content-fnref-spii&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 9&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>security</category><category>https</category><category>go</category></item><item><title>Universal time UnmarshalJSON implementation</title><link>https://safigo.dev/posts/2022-05-08-universal-time-unmarshaljson/</link><guid isPermaLink="true">https://safigo.dev/posts/2022-05-08-universal-time-unmarshaljson/</guid><description>The final implementation for the unviersal time parser that implements the UnmarshalJSON interface</description><pubDate>Sun, 08 May 2022 20:01:24 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;We have done with two complecated steps by writing the parsers for different date time formats:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2022-05-06-parse-timestamp/&quot;&gt;Time from timestamp formats&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://safigo.dev/posts/2022-05-07-parse-time-strings/&quot;&gt;Time from non timestamp formats like RFC3339&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The next and final step will be to write a real world function that solves the real and actual problem.
We need to parse the JSON field from different formats with different data types.&lt;/p&gt;
&lt;p&gt;I will go though couple of investigation steps before we will write the real code.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;I’ll use &lt;a href=&quot;https://go.dev/&quot;&gt;Golang&lt;/a&gt; for all code examples, but you can use any other languages base on the provided algorithm.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Task overview&lt;/h2&gt;
&lt;p&gt;Current task is to write a Golang type that can be used in JSON parsing pipeline.
This field should support couple of use cases that we already reviewed in previous articles.&lt;/p&gt;
&lt;p&gt;We received a JSON field with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Numeric types and we expect to parse it as a timestamp.&lt;/li&gt;
&lt;li&gt;String type and we expect to parse it as a timestamp.&lt;/li&gt;
&lt;li&gt;String type and we expect to parse it as a some layout from the provided list.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Expectations&lt;/h3&gt;
&lt;p&gt;Based on the above use cases, we expect to see the following list of JSON fields:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;num_seconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1651808102&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;num_milliseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1651808102363&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;num_microseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1651808102363368&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;num_nanoseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1651808102363368423&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;hex_seconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;0x62749766&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_seconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;1651808102&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_milliseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;1651808102363&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_microseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;1651808102363368&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_nanoseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;1651808102363368423&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_rfc3339&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;2022-05-06T03:35:02Z&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_rfc3339_nano&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;2022-05-06T03:35:02.363368423Z&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_rfc1123&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Fri, 06 May 2022 03:35:02 UTC&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_rfc850&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Friday, 06-May-22 03:35:02 UTC&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  &quot;str_rfc822&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;06 May 22 03:35 UTC&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obviously, it’s not full list of types, but as we already tested comprehensive list of cases before, we can simplify it right now.&lt;/p&gt;
&lt;p&gt;We added hex seconds field, just in to see it works as well, because of the magic of &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;strconv.ParseInt&lt;/code&gt; function.&lt;/p&gt;
&lt;h3&gt;UnmarshalJSON interface overview&lt;/h3&gt;
&lt;p&gt;Before the implementation we need to consider the Golang way of custom JSON data types implementation.&lt;/p&gt;
&lt;p&gt;Golang contains the interface &lt;a href=&quot;https://pkg.go.dev/encoding/json#Unmarshaler&quot;&gt;Unmarshaler&lt;/a&gt; with one method &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;UnmarshalJSON([]byte) error&lt;/code&gt;.
It means that we need to implement only one method to parse the JSON field.&lt;/p&gt;
&lt;p&gt;There is an example of the simple implementation of the interface where we just need to separate the string with a value separated by underscore &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;_&lt;/code&gt; in a JSON field to 2 variables:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;encoding/json&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;strings&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; unmarshaled&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  part1&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  part2&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;u &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;unmarshaled&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnmarshalJSON&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  str&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  parts&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; strings&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Split&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; len&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;parts&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; errors&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;New&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;invalid format&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  u&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;part1&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; parts&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  u&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;part2&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; parts&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; jsonType&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  T&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; unmarshaled&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;t&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  var&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; jt&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; jsonType&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  json1&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;{&quot;t&quot;: &quot;one_two&quot;}&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; json&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unmarshal&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;json1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;    panic&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;part1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;part2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  json2&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;{&quot;t&quot;: &quot;onetwo&quot;}&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; json&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unmarshal&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;json2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;    panic&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;part1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;part2&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;plain&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&quot;one two&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;panic: invalid format&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;goroutine 1 [running]:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;main.main()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        /Users/aohorodnyk/projects/anton.ohorodnyk.name/main.go:47 +0x13c&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;exit status 2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first input parsed correctly, but the second one failed.&lt;/p&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;The final implementation will contain the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check if the JSON field is a numeric, because of it’s the fastest condition.
&lt;ol&gt;
&lt;li&gt;If it’s a numeric, we can parse it as a timestamp.&lt;/li&gt;
&lt;li&gt;Use the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;strconv.ParseInt&lt;/code&gt; function to parse it.&lt;/li&gt;
&lt;li&gt;The &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;strconv.ParseInt&lt;/code&gt; function will parse the type based on the prefix of the string. If the prefix is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;0x&lt;/code&gt;, it will be parsed as a hexadecimal number. 0b as a binary number, etc. By default it will be parsed as a decimal number.&lt;/li&gt;
&lt;li&gt;If we can’t prase the numeric value as an integer, then return the error, since we do not know waht to do with the value.&lt;/li&gt;
&lt;li&gt;Otherwise set the time and finish the processing.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Otherwise the value is a string. For strings we need to trim quotes to make the value a plain string.&lt;/li&gt;
&lt;li&gt;Try to parse the string with all supported layouts.&lt;/li&gt;
&lt;li&gt;If we successfuly parsea the string with a some listed layouts, then set the time and finish the processing.&lt;/li&gt;
&lt;li&gt;If we did not find the needed layout, try to parse the string as a timestamp.&lt;/li&gt;
&lt;li&gt;If we successfuly parse the string as a timestamp, then set the time and finish the processing.&lt;/li&gt;
&lt;li&gt;Otherwise return the error.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following code example implements the algorithm described above.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;encoding/json&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;strconv&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;strings&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// List of supported time layouts.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; formats&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339Nano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123Z&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC850&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC822Z&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC822&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Layout&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RubyDate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;UnixDate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ANSIC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampNano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampMicro&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampMilli&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Stamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Kitchen&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;MaxInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;maxNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;maxMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxSeconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;maxMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;MinInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;minNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;minMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minSeconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;minMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; InternalTime&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;it &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;InternalTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnmarshalJSON&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Make sure that the input is not empty&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; len&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; errors&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;New&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;empty value is not supported&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // If the input is not a string, try to parse it as a number, otherwise return an error.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; data&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    timeInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; strconv&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ParseInt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    it&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timeInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // If the input is a string, trim quotes.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  str&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; strings&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Trim&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Parse the string as a time using the supported layouts.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  parsed&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    it&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; parsed&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // As the final attempt, try to parse the string as a timestamp.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  timeInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; strconv&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ParseInt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    it&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timeInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; errors&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;New&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Unsupported time format&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; jsonType&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  NumSeconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;      InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;num_seconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  NumMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;num_milliseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  NumMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;num_microseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  NumNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;num_nanoseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  HexSeconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;hex_seconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrSeconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;      InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_seconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_milliseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_microseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_nanoseconds&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrRFC3339&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;     InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_rfc3339&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrRFC3339Nano&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_rfc3339_nano&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrRFC1123&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;     InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_rfc1123&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrRFC850&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;      InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_rfc850&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  StrRFC822&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;      InternalTime&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;json:&quot;str_rfc822&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  var&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; jt&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; jsonType&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  json1&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;num_seconds&quot;: 1651808102,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;num_milliseconds&quot;: 1651808102363,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;num_microseconds&quot;: 1651808102363368,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;num_nanoseconds&quot;: 1651808102363368423,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;hex_seconds&quot;: &quot;0x62749766&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_seconds&quot;: &quot;1651808102&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_milliseconds&quot;: &quot;1651808102363&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_microseconds&quot;: &quot;1651808102363368&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_nanoseconds&quot;: &quot;1651808102363368423&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_rfc3339&quot;: &quot;2022-05-06T03:35:02Z&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_rfc3339_nano&quot;: &quot;2022-05-06T03:35:02.363368423Z&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_rfc1123&quot;: &quot;Fri, 06 May 2022 03:35:02 UTC&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_rfc850&quot;: &quot;Friday, 06-May-22 03:35:02 UTC&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;    &quot;str_rfc822&quot;: &quot;06 May 22 03:35 UTC&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  }&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; json&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unmarshal&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;json1&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;    panic&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;jt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// {2022-05-05 20:35:02 -0700 PDT 2022-05-05 20:35:02.363 -0700 PDT 2022-05-05 20:35:02.363368 -0700 PDT 2022-05-05 20:35:02.363368423 -0700 PDT 2022-05-05 20:35:02 -0700 PDT 2022-05-05 20:35:02 -0700 PDT 2022-05-05 20:35:02.363 -0700 PDT 2022-05-05 20:35:02.363368 -0700 PDT 2022-05-05 20:35:02.363368423 -0700 PDT 2022-05-06 03:35:02 +0000 UTC 2022-05-06 03:35:02.363368423 +0000 UTC 2022-05-06 03:35:02 +0000 UTC 2022-05-06 03:35:02 +0000 UTC 2022-05-06 03:35:00 +0000 UTC}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  switch&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; minMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; minMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Microsecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in microseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; minSeconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Millisecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in milliseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in seconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; maxSeconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in seconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; maxMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Millisecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in milliseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; maxMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Microsecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in microseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; _&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    parsedTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Parse&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; parsedTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{}, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;could not parse time: &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code covers positive test cases and proves the algorithm works without any issues and implementation is correct.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In the latest three articles we implemented the universal time parser that can be used to improve clients’ developer experience.
It can help to decrease amount of production bugs and errors.&lt;/p&gt;
&lt;p&gt;I hope these articles will be helpful to you and your team.&lt;/p&gt;
&lt;p&gt;Fill free to ask any question you might have.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>time</category><category>json</category><category>parsing</category></item><item><title>Parse time from different non timestamp formats</title><link>https://safigo.dev/posts/2022-05-07-parse-time-strings/</link><guid isPermaLink="true">https://safigo.dev/posts/2022-05-07-parse-time-strings/</guid><description>Parse timestamp from different clients and from different developers</description><pubDate>Sun, 08 May 2022 03:48:20 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In previous article, we implemented the efficient solution to parse timestamps in &lt;a href=&quot;https://safigo.dev/posts/2022-05-06-parse-timestamp/&quot; title=&quot;Parse timestamp formats&quot;&gt;different timestamp formats (seconds, milliseconds, microseconds, nanoseconds)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As I mentioned in the previous article, we can receive a string formatted date time from a client, when we expected string timestamp in seconds.&lt;/p&gt;
&lt;p&gt;Obviously we hardcoded some solution to support the specific format on a server (as we are expecting to find this issue on production with a production client), but we still would like to make it more universan and forget about the problem for a while.&lt;/p&gt;
&lt;p&gt;Let’s implement the solution!&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;I’ll use &lt;a href=&quot;https://go.dev/&quot;&gt;Golang&lt;/a&gt; for all code examples, but you can use any other languages base on the provided algorithm.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Issue overview&lt;/h2&gt;
&lt;p&gt;Before we will start writing code, we need to understand the issue.&lt;/p&gt;
&lt;h3&gt;Expectations&lt;/h3&gt;
&lt;p&gt;To simplify current task, let’s assume that we have a string field and we need to write a function that will support a multiple time formats.&lt;/p&gt;
&lt;p&gt;There are our expectations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We have a string field where we expect to receive a RFC339 date time information.&lt;/li&gt;
&lt;li&gt;Our expectation is to see the timestamp in a range of dates and times between &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;current time - 3 days&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;current time + 3 days&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We use a language with strict type checking. We accept ONLY string value in our JSON field.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Issue identification&lt;/h3&gt;
&lt;p&gt;What do we unexpectedly see in our logs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the log we have found an error like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;0001-01-01 00:00:00 +0000 UTC parsing time &quot;Sat, 07 May 2022 19:22:10 PDT&quot; as &quot;2006-01-02 15:04:05&quot;: cannot parse &quot;Sat, 07 May 2022 19:22:10 PDT&quot; as &quot;2006&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;And also we have found this type of errors &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;0001-01-01 00:00:00 +0000 UTC parsing time &quot;05/07 07:22:54PM &apos;22 -0700&quot; as &quot;2006-01-02 15:04:05&quot;: cannot parse &quot;7 07:22:54PM &apos;22 -0700&quot; as &quot;2006&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Possible wrong formats&lt;/h3&gt;
&lt;p&gt;After some investigation we found the following formats used by clients:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;time.Layout&lt;/code&gt; from Golang -&gt; &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;01/02 03:04:05PM &apos;06 -0700&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;RFC1123&lt;/code&gt; with a format &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Mon, 02 Jan 2006 15:04:05 MST&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It means that some our clients uses wrong standardized formats, instead of expected RFC3339.
As well with identified formats we assumed that clients could use some more different formats and we need to communicate with all our client teams or partners to identify all possible formats.&lt;/p&gt;
&lt;h3&gt;Issue solving steps&lt;/h3&gt;
&lt;p&gt;Based on our investigation to fix the issue for the most future cases we need to do these fixes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support the most popular formats.&lt;/li&gt;
&lt;li&gt;Design the extensible API to support for additional formats.&lt;/li&gt;
&lt;li&gt;Try do not overcomplicate the solution, for this article.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Known limitations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Surely this function will not support all possible formats, so, we will need to extend it with more formats, when needed.&lt;/li&gt;
&lt;li&gt;We will use only formats from the predefined list in standard Golang library.&lt;/li&gt;
&lt;li&gt;There are possible conflicts between different formats. The order of provided formats is important.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;Before we start writing code, we need to do some preparations.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Understand on how to parse the date time in Golang.&lt;/li&gt;
&lt;li&gt;Find the list of supported formats in standard Golang library.&lt;/li&gt;
&lt;li&gt;Implement the function.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;How to parse the date time in Golang&lt;/h3&gt;
&lt;p&gt;Fortunately, Golang supports pretty simple API to parse the date time from a string in different formats.
However, It has unusual layout’s format.&lt;/p&gt;
&lt;p&gt;To parse the date time, we need to use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;time.Parse&lt;/code&gt; function.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  now&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()                                                 &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Get current date time.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  parsed&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Parse&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Parse current date time in RFC3339 format.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;parsed&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)                                          &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-07 20:07:11 -0700 PDT &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the example above, we parse the current date time in &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;RFC3339&lt;/code&gt; format that contains the layout &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2006-01-02T15:04:05Z07:00&lt;/code&gt;.
As we can see, in golang we use the specific time date as a layout to specify the format that we will parse.
It’s unusual, but since we are not going to write our own formats, the task will not require detailed knowledge of these internal implementations.&lt;/p&gt;
&lt;p&gt;As we can see, there are two different parameters returned from &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;time.Parse&lt;/code&gt; function: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;time&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt;.
If &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;error&lt;/code&gt; is nil, then we sucessfully parsed the date time, otherwise something went wrong.&lt;/p&gt;
&lt;p&gt;Let’s see an example with different formats:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  now&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()                                                 &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Get current date time.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  parsed&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Parse&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Parse current date time in RFC3339 format.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;parsed&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)                                          &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 0001-01-01 00:00:00 +0000 UTC parsing time &quot;Sat, 07 May 2022 20:09:12 PDT&quot; as &quot;2006-01-02T15:04:05Z07:00&quot;: cannot parse &quot;Sat, 07 May 2022 20:09:12 PDT&quot; as &quot;2006&quot;.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see in the output, we got an empty date time &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;0001-01-01 00:00:00 +0000 UTC&lt;/code&gt; and an error &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;parsing time &quot;Sat, 07 May 2022 20:09:12 PDT&quot; as &quot;2006-01-02T15:04:05Z07:00&quot;: cannot parse &quot;Sat, 07 May 2022 20:09:12 PDT&quot; as &quot;2006&quot;&lt;/code&gt; about wrong format.&lt;/p&gt;
&lt;p&gt;We will use this behavior to parse the date time in different formats.&lt;/p&gt;
&lt;h3&gt;List of supported formats&lt;/h3&gt;
&lt;p&gt;As I mentioned before, we need to support all formats from the standard Golang library.&lt;/p&gt;
&lt;p&gt;All supported formats are listed in the time package of the standard library. We can find it in &lt;a href=&quot;https://pkg.go.dev/time#pkg-constants&quot;&gt;the documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ll list all supported formats in the current latest Golang version:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; time&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  Layout&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;01/02 03:04:05PM &apos;06 -0700&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; // The reference time, in numerical order.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  ANSIC&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;       =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Mon Jan _2 15:04:05 2006&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  UnixDate&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Mon Jan _2 15:04:05 MST 2006&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RubyDate&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Mon Jan 02 15:04:05 -0700 2006&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RFC822&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;02 Jan 06 15:04 MST&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RFC822Z&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;02 Jan 06 15:04 -0700&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; // RFC822 with numeric zone&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RFC850&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Monday, 02-Jan-06 15:04:05 MST&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RFC1123&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Mon, 02 Jan 2006 15:04:05 MST&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RFC1123Z&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Mon, 02 Jan 2006 15:04:05 -0700&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; // RFC1123 with numeric zone&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RFC3339&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;2006-01-02T15:04:05Z07:00&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  RFC3339Nano&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;2006-01-02T15:04:05.999999999Z07:00&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  Kitchen&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;3:04PM&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Handy time stamps.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  Stamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Jan _2 15:04:05&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  StampMilli&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Jan _2 15:04:05.000&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  StampMicro&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Jan _2 15:04:05.000000&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  StampNano&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Jan _2 15:04:05.000000000&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Efficient solution&lt;/h3&gt;
&lt;p&gt;For implementation we will use the simplest possible algorithm:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Iterate over all supported formats.&lt;/li&gt;
&lt;li&gt;Parse the receved string with the current format.&lt;/li&gt;
&lt;li&gt;If the returned error is equal to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;nil&lt;/code&gt;, then we found the correct format. We can return from the function.&lt;/li&gt;
&lt;li&gt;Otherwise, we need to continue the iteration.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The intermediate solution:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  t&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Date&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;2022&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;May&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;23&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;734423&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Layout&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))  &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 0001-01-01 00:00:00 +0000 UTC could not parse time: 05/23 07:03:05AM &apos;22 +0000&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  var&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; formats&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; _&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    parsedTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Parse&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; parsedTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{}, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;could not parse time: &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the code with the example we iterated over two formats: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;RFC3339&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;RFC1123&lt;/code&gt;. We wrote the test where we tried to parse three different formats with the same date time string. As we can see both supported formats are parsed correctly.&lt;/p&gt;
&lt;p&gt;There is the limitation that we can recognize based on the above example: we can’t parse sequantly formats that are sub-formats of the next format.
So, we need to be sure that we provide time layouts in the list formats from the most specific to the most general.&lt;/p&gt;
&lt;p&gt;Implementing the function that will cover all requirements we already specified:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Specify all formats in the specific order.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  formats&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339Nano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123Z&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC850&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC822Z&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC822&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Layout&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RubyDate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;UnixDate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ANSIC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampNano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampMicro&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampMilli&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Stamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Kitchen&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  t&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Date&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;2022&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;May&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;23&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;234734423&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339Nano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05.234734423 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123Z&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))    &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 +0000 &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC1123&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC850&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC822Z&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:00 +0000 +0000 &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC822&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:00 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Layout&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 +0000 &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RubyDate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))    &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05 +0000 +0000 &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;UnixDate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))    &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:00 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ANSIC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))       &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:00 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampNano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))   &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-23 07:03:05.234734423 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampMicro&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))  &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 0000-05-23 07:03:05.234734 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StampMilli&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))  &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 0000-05-23 07:03:05.234 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Stamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))       &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 0000-05-23 07:03:05 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Kitchen&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)))     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 0000-01-01 07:03:00 +0000 UTC &amp;#x3C;nil&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; _&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; formats&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    parsedTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Parse&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; parsedTime&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{}, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;could not parse time: &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;dt&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Usually we see the implementation with all possible test cases to be sure that our algorithm is correct and it supports all required formats.&lt;/p&gt;
&lt;p&gt;Looks like all formats were parsed without any issues and we will assume that this algorithm is correct and usable for our application.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this article we solved one more issue related to parsing date time string.
Now we can assume that our clients are covered and safe with all predefined formats.&lt;/p&gt;
&lt;p&gt;Current implementation can be used without any restrictions in all your projects. But, pay more attention that you covered all required formats by your business. Probably, you will need to add more formats to the list.&lt;/p&gt;
&lt;p&gt;I hope this article will save some time for you.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>time</category><category>parsing</category></item><item><title>Parse timestamp formats</title><link>https://safigo.dev/posts/2022-05-06-parse-timestamp/</link><guid isPermaLink="true">https://safigo.dev/posts/2022-05-06-parse-timestamp/</guid><description>Parse timestamp from different clients and from different developers</description><pubDate>Fri, 06 May 2022 03:46:23 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Have you ever had a situation when different clients send milliseconds in requests to a back-end that expects timestamp in seconds?&lt;/p&gt;
&lt;p&gt;If not, you are lucky person. Unfortunately, it’s so popular issue in my experience.
I even cannot count a number of bugs related to the specific issue.&lt;/p&gt;
&lt;p&gt;Every time we find this issue on a client, we need to find the best on how to solve it.
If a front-end is web-site, it’s littery not an issue and can be simply fixed and redeliver to all users in short period of time.
But, if the front-end is a client application, it could be much more complicated to redeliver the fix to all clients in some predictable period of time.&lt;/p&gt;
&lt;p&gt;In my point of view the best way to fix the issue in this specific situation is to fix everything on backend and support two different types of payload.
We have predictable time expectations when we can fix the issue, we know how can we deliver the fix to ALL users, etc.&lt;/p&gt;
&lt;p&gt;In the current example when we expect to receive the unix timestamp in seconds, but receive it in milliseconds.
We can fix it by adding support for both possible values to our parser.&lt;/p&gt;
&lt;p&gt;Moreover, we know about the situations when a client sets the RFC3339 as a string field type, instead of int with a timestamp.&lt;/p&gt;
&lt;p&gt;So, we have fixed the issues for our production, let’s relax.
But, as we discussed, this issue have happened multiple time, let’s try to think about the solution to prevent this issue in future?&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;I’ll use &lt;a href=&quot;https://go.dev/&quot;&gt;Golang&lt;/a&gt; for all code examples, but you can use any other language base on the provided algorithm.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Issue overview&lt;/h2&gt;
&lt;p&gt;Before we will start writing code, we need to understand the issue.&lt;/p&gt;
&lt;h3&gt;Expectations&lt;/h3&gt;
&lt;p&gt;There are our expectations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We have an &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; field where we expect to receive the unix timestamp in seconds.&lt;/li&gt;
&lt;li&gt;We expect to see always possitive int numbers in this field.&lt;/li&gt;
&lt;li&gt;Our expectation is to see the timestamp in a range of dates and times between &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;current time - 3 days&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;current time + 3 days&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We use a language with strict type checking. We accept ONLY int value in our JSON field.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Issue identification&lt;/h3&gt;
&lt;p&gt;What do we unexpectedly see in our stored data or logs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Instead of &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2022-05-05T10:43:27-07:00&lt;/code&gt; we see &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;54312-08-04T05:24:35-07:00&lt;/code&gt; in our storage.&lt;/li&gt;
&lt;li&gt;Instead of processed requests we see some errors in logs that JSON could not be parsed, because of string provided in a field, instead of expected int.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Possible wrong formats&lt;/h3&gt;
&lt;p&gt;After some investigation we found that the both issues are related to the following wrong values:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We see in the storage the future date &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;54313-06-15T01:03:45Z&lt;/code&gt;, instead of the current date &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2022-05-06T01:16:23Z&lt;/code&gt;, because of the client used milliseconds instead of seconds during timestamp generation.&lt;/li&gt;
&lt;li&gt;We see in logs an error that JSON could not be parsed, because of string provided in a field, instead of expected int, because of the client sent us some string value in the field.
&lt;ol&gt;
&lt;li&gt;The client set the timestamp in a string field, instead of int, during JSON generation.&lt;/li&gt;
&lt;li&gt;The client sent us the date time in an &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;RFC3339&lt;/code&gt; format, instead of unix timestamp in seconds.&lt;/li&gt;
&lt;li&gt;The client used some other date time format to send us the date time.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Issue solving steps&lt;/h3&gt;
&lt;p&gt;Based on our investigation to fix the issue for the most future cases we need to do these fixes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add support of all possible values for our timestamp field: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;seconds&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;milliseconds&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;microseconds&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;nanoseconds&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add support of the timestamp field in a string type (we will not solve it in this article).&lt;/li&gt;
&lt;li&gt;Add support of the date time formats like: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;RFC3339&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;RFC3339Nano&lt;/code&gt;, etc (we will not solve it in this article).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Known limitations&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In this document we will use Golang language for all code examples.&lt;/li&gt;
&lt;li&gt;We will solve the issue with write the functions that will parse .&lt;/li&gt;
&lt;li&gt;As we are fixing the specific use case with a timestamp, we are not going to support all range of possible date times.
&lt;ol&gt;
&lt;li&gt;We will surely support the range between &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;1970-04-17T18:02:52Z&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2262-04-11T23:47:16Z&lt;/code&gt; years.&lt;/li&gt;
&lt;li&gt;If you need dates after &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2262-04-11T23:47:16Z&lt;/code&gt; year or before &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;1970-04-17T18:02:52Z&lt;/code&gt;, you will need to adjust the solution for your specific use case.&lt;/li&gt;
&lt;li&gt;Negative values are supported for the timestamp. But they have the same restrictions as positive values. The supported range for the negative values betwee &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;1969-09-15T22:57:07.963145225-07:00&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;1677-09-20T16:19:45.145224192-07:52&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;We will solve only timestamp parsing issue, without string dates parsing.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Looks like we are done with the issue formalization, let’s move to the implementation side.&lt;/p&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;To write the code we need to understand on how the timestamp works with different time formats.
What can we use and how to identify the edges of the time range?&lt;/p&gt;
&lt;p&gt;First of all let’s try to understand on how timestamp for different time formats works.&lt;/p&gt;
&lt;h3&gt;Timestamp&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Unix_time&quot;&gt;Timestamp&lt;/a&gt; is a number of seconds since January 1, 1970 UTC.
To use more granular time we just add more digits to the timestamp. For example, to store a timestamp in milliseconds we add 3 digits to the timestamp (multiple seconds to 1000 to get milliseconds).&lt;/p&gt;
&lt;p&gt;All modern implementation for the timestamp format uses &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; type, to solve the issue of 2038 year’s problem&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2022-05-06-parse-timestamp/#user-content-fn-y2k38&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Tht meximum date for &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;292277026596-12-04T15:30:07Z&lt;/code&gt;. We can assume that we will never met this limit.&lt;/p&gt;
&lt;p&gt;To collect data in milliseconds, microseconds and nanoseconds we uses &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; as well in many cases.
The max date time for &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2262-04-11T23:47:16Z&lt;/code&gt;.
It’s too far in the future to be a problem as well.&lt;/p&gt;
&lt;h3&gt;Golang introduction&lt;/h3&gt;
&lt;p&gt;So, now we know how the timestamp works, but what the next?&lt;/p&gt;
&lt;p&gt;Before we will start, let’s see on how to parse dates in Golang, if we are going to work with this language in the further steps.&lt;/p&gt;
&lt;p&gt;In Golang we use the &lt;a href=&quot;https://pkg.go.dev/time&quot;&gt;time&lt;/a&gt; package to parse dates and times.&lt;/p&gt;
&lt;p&gt;To convert &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; timestamp in seconds to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;time.Time&lt;/code&gt; we use the &lt;a href=&quot;https://pkg.go.dev/time#Unix&quot;&gt;time.Unix(int64, 0)&lt;/a&gt; function. Let’s convert &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; timestamp in seconds to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;time.Time&lt;/code&gt; and print it in RFC3339 format.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  t&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1651804700&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Convert inte64 timestamp in seconds to time.Time&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  str&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Convert time.Time to RFC3339 format in string.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)                  &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-05T19:38:20-07:00&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let’s see how to print the same timestamp in nanoseconds.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  nanosecondMultiplier&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Second&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  t&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1651804700&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nanosecondMultiplier&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Convert inte64 timestamp in seconds to time.Time&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  str&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)                      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Convert time.Time to RFC3339 format in string.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)                                       &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-05T19:38:20-07:00&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All timestamps in microseconds and milliseconds we will convert to nanoseconds and use the sacond example to parse it.&lt;/p&gt;
&lt;h3&gt;Identify the edges of the time range&lt;/h3&gt;
&lt;p&gt;We already know how to parse the dates, but the question, how to identify the edges of the time range?&lt;/p&gt;
&lt;p&gt;The simplest solution would be just to parse the timestamp in a loop and check the timeframes to identify the right date time.
We will parse numbers as nanoseconds and if the number less than the magic year (let’s choose 1980), then divide it by 1000 and try again. Let’s see the code:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1651804700000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// timestamp in milliseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  for&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// If int will overflow, we will get 0.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    t&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Try to parse the timestamp in nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Year&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1980&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Year&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 2100&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;      println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Print the timestamp in RFC3339 format.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; // Exit the loop.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; *=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt; // Try to convert to the next level (seconds -&gt; milliseconds -&gt; microseconds -&gt; nanoseconds) and try again.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will work, but this algorithm is not the most efficient, because of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It can go overflow.&lt;/li&gt;
&lt;li&gt;We do multiple covertions int to time.&lt;/li&gt;
&lt;li&gt;We perform multiple calculations.&lt;/li&gt;
&lt;li&gt;We need to choose more accurate magic years.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Efficient solution&lt;/h3&gt;
&lt;p&gt;First of all, instead of multiple calculations we can precalculate the most efficient timestamps and just verify with them.
And if we find the required range, do one time calculation.&lt;/p&gt;
&lt;p&gt;To find the most efficient timestamps, let’s try to find the maximum year we can effort with the most granular format.
Our the most granular format is nanoseconds. Let’s see:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;MaxInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Maximum available timestamp.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  t&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Parse the maximum timestamp.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2262-04-11T23:47:16Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 9223372036854775807&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see the maximum available &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int64&lt;/code&gt; timestamp is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;9223372036854775807&lt;/code&gt; and it equals to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2262-04-11T23:47:16Z&lt;/code&gt; date time.&lt;/p&gt;
&lt;p&gt;Based on our previous knowledge if we will devide this number by 1000 we will get the next less granular format.
Let’s see it in the example:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  nano&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;MaxInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  micro&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nano&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  milli&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;micro&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  sec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;milli&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Print all timestamps.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;seconds: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)        &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// seconds:  9223372036&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;milliseconds: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;milli&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// milliseconds:  9223372036854&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;microseconds: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;micro&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// microseconds:  9223372036854775&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;nanoseconds: &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)   &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// nanoseconds:  9223372036854775807&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Parse seconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2262-04-11T23:47:16Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Parse seconds by converting it to nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Second&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2262-04-11T23:47:16Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Let&apos;s see what time will we see if we try to parse the seconds as milliseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Millisecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1970-04-17T18:02:52Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Parse milliseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;milli&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Millisecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2262-04-11T23:47:16Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Let&apos;s see what time will we see if we try to parse the milliseconds as microseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;milli&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Microsecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1970-04-17T18:02:52Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Parse microseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;micro&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Microsecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2262-04-11T23:47:16Z// Let&apos;s see what time will we see if we try to parse the microseconds as nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;micro&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1970-04-17T18:02:52Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Parse nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2262-04-11T23:47:16Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the negative values we will follow the same logic, but we will start from the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;math.MinInt64&lt;/code&gt; and go down.
In the next code snippet with the solution we will see the actual implementation.&lt;/p&gt;
&lt;p&gt;As we can see the simple and pretty efficient solution is to just base max timestamps on max int64.
Let’s write the function that will efficiently parse the timestamps independent of the format.&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;MaxInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;maxNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;maxMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  maxSeconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;maxMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;math&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;MinInt64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;minNanoseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;minMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;  minSeconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;minMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Positive time.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  now&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Date&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;2022&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;May&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;06&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;03&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;35&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;02&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;363368423&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  sec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1651808102&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  millisec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnixMilli&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;millisec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;millisec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1651808102363&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  microsec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnixMicro&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;microsec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;microsec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1651808102363368&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  nanosec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnixNano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nanosec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nanosec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1651808102363368423&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 2022-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // Negative time.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  now&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Date&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;1830&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;May&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;06&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;03&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;35&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;02&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;363368423&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  sec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;sec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// -4407164698&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1830-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  millisec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnixMilli&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;millisec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;millisec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// -4407164697637&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1830-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  microsec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnixMicro&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;microsec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;microsec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// -4407164697636632&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1830-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  nanosec&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UnixNano&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rfc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nanosec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Format&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;nanosec&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// -4407164697636631577&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;  println&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rfc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)     &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// 1830-05-06T03:35:02Z&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; parseTimestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  switch&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; minMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; minMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Microsecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in microseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; minSeconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Millisecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in milliseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Before 1970 in seconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; maxSeconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in seconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; maxMilliseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Millisecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in milliseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  case&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; maxMicroseconds&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;*int64&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Microsecond&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in microseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Unix&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// After 1970 in nanoseconds.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this article we solved a real-world problem, surely affected more than one person.
I hope this solution will help someone to improve their product and improve user-experience of their API.&lt;/p&gt;
&lt;p&gt;Do not forget, that every complicated problem can be solved with a simple and efficient&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2022-05-06-parse-timestamp/#user-content-fn-efficient&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; solution.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Year 2038 is the problem when the max value of &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int32&lt;/code&gt; in seconds will be reached on &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;2038-01-19T03:14:07Z&lt;/code&gt;. &lt;a href=&quot;https://safigo.dev/posts/2022-05-06-parse-timestamp/#user-content-fnref-y2k38&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;By efficient I mean that the solution has efficient cpu and memory consumption. It will help to save money, improve user and developer experience as well as saving the world by decreasing electrycity consumption. &lt;a href=&quot;https://safigo.dev/posts/2022-05-06-parse-timestamp/#user-content-fnref-efficient&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>time</category><category>parsing</category></item><item><title>Kafka as a message queue</title><link>https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/</link><guid isPermaLink="true">https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/</guid><description>Small, but the significant part for people who wants to choose Kafka as a message queue</description><pubDate>Tue, 27 Jul 2021 17:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Small but crucial part for people who wants to choose Kafka as a message queue&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kafka is an excellent tool for data processing in streaming mode. It can help build great tools, especially when analyzing some streaming data (like user analytics, some events, etc. Moreover, Kafka as storage with Kafka streams will help process even some data with “big data”.&lt;/p&gt;
&lt;p&gt;However, this article will describe only one use case where Kafka can be used.&lt;/p&gt;
&lt;p&gt;This task has the name “message queue”. It is an essential part of every project I was involved in. People try to solve this task in different ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a designed tool for that (like NSQ, RabbitMQ, Gearman, etc.)&lt;/li&gt;
&lt;li&gt;Build message queue on the top of their DB (PostgreSQL, MySQL, Redis, etc.)&lt;/li&gt;
&lt;li&gt;Try to delegate all tasks required message queue to external services, to avoid an implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kafka pretends to be used as a designed tool for this specific task and provides incredible guarantees. Therefore, we will review only this part. I hope it will help us to understand Kafka is the right tool for the next project.&lt;/p&gt;
&lt;p&gt;Also, we will skip the partitions&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fn-main_concepts&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; part.&lt;/p&gt;
&lt;h3&gt;Message queue (MSQ)&lt;/h3&gt;
&lt;p&gt;Before reviewing the implementation of the pattern in Kafka, let’s overview it is in general.&lt;/p&gt;
&lt;p&gt;Simple message processing usually splits into two different parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Producer (who sends a message to a queue)&lt;/li&gt;
&lt;li&gt;Consumer (who consumes the message from the queue)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Suppose we want to guarantee that message was processed at least once. In that case, we need to introduce some acknowledged method to our message processing pattern. Let’s add the commit method:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Committer (acknowledge message queue that message processed and we want to stop sending it to a consumer)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a result, we will have three methods for our message queue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Produce&lt;/li&gt;
&lt;li&gt;Consume&lt;/li&gt;
&lt;li&gt;Commit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example with the simple flow with one message:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A producer sends a message to a queue&lt;/li&gt;
&lt;li&gt;A consumer received this message and tried to process it&lt;/li&gt;
&lt;li&gt;If the consumer fails (or after some time, depends on implementation) and a message was not committed, the consumer will receive this message one more time (go to option 2)&lt;/li&gt;
&lt;li&gt;Commit message (do not send it to a consumer anymore)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Message Queue Diagram&quot; width=&quot;703&quot; height=&quot;477&quot; src=&quot;https://safigo.dev/_astro/2021-07-27-kafka-as-a-message-queue-diagrams-msq-general.Bk4_l8R8_r0KBe.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Kafka message queue key features&lt;/h2&gt;
&lt;p&gt;First of all, let’s overview the main features you will deal with when choosing Kafka as a message queue.&lt;/p&gt;
&lt;p&gt;We need to understand the main concepts we will work with this information. We will not only deal with event publishing and consumption. There are more things we will deal with.&lt;/p&gt;
&lt;h3&gt;Key names&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Topic&lt;/strong&gt; - something like database or collection in other databases. In a topic Kafka stores all events pushed to it. Consumers use a topic as well to read messages from it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Broker&lt;/strong&gt; - Kafka node processes events.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partition&lt;/strong&gt; - Kafka has a feature to scale between nodes and consumers. For this reason, the Kafka team introduced a partition rate (it’s just int number). This number is used in the scope of message distribution between partitions. Partitions assign to consumers and brokers uniquely.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Producer&lt;/strong&gt; - an application that pushes new events to a topic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consumer&lt;/strong&gt; - an application that reads messages from a topic, processes them and commits them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Message stream&lt;/h3&gt;
&lt;p&gt;Message queue in Kafka builds over Kafka message stream. Actually, the message stream is just storage with all messages sequentially persisted. Data from the storage can be read by batches with a specific size in bytes.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Kafka can be used as a storage to read the data and build some decisions on top of it.
This solution is usually used in Data Science.
If we need to speed up calculation over the data, we can use Kafka Streams&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fn-kafka_streams&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When we want to use Kafka as a message queue. We read a batch of messages[^read_batch_message] with some shifts, parse them and start to process.&lt;/p&gt;
&lt;h3&gt;Partitions&lt;/h3&gt;
&lt;p&gt;This article should not focus on the partitions feature in Kafka. Still, unfortunately, it’s impossible to skip the topic in a consumer/producer context.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Warn: All messages with the same key (for example, user_uuid) will be sent to the same partition.&lt;/p&gt;
&lt;p&gt;BE CAREFUL!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When we create a topic, we can specify the number of partitions (for example, 3). Then, based on the message key (usually generated UUIDv4), the Kafka client will choose one of the partitions and send a message to this partition.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Kafka partitions&quot; width=&quot;1071&quot; height=&quot;472&quot; src=&quot;https://safigo.dev/_astro/2021-07-27-kafka-as-a-message-queue-diagrams-kafka-partitions.Bj930Wf6_Z1WjjMI.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;The diagram above shows how Kafka clients sort messages between partitions.
Partitions from topics used for Kafka distribution (add new nodes to a cluster) and consumer distribution as well &lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#consumer&quot;&gt;see consumer paragraph&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Producer&lt;/h3&gt;
&lt;p&gt;The producer works most simply. We just produce message&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fn-producer&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; (send it to Kafka). Nothing special we want to discuss.&lt;/p&gt;
&lt;h3&gt;Consumer&lt;/h3&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;As we agreed before, we will not review the partition part. In this stage, we will work only with group readers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kafka provides &lt;em&gt;consumer groups&lt;/em&gt; feature. &lt;em&gt;Group ID&lt;/em&gt; should be provided&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fn-consumer_group_id_partitions&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; by a consumer that reads from a topic.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#partitions&quot;&gt;Partitions&lt;/a&gt; used to distribute messages between consumers.
The group ID is used by Kafka to identify messages that need to be delivered to a specific consumer. It automatically distributes partitions between consumers from the same group (Group ID).&lt;/p&gt;
&lt;p&gt;Two consumers from the same group will not receive the same message. Instead, every consumer will follow their specific partition(s) and receive a message from them.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;If we use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;user_uuid&lt;/code&gt; as a message key, then all messages from the same user will always be sent to the same partition and processed by the same consumer&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;Consumer partitions&quot; width=&quot;1062&quot; height=&quot;949&quot; src=&quot;https://safigo.dev/_astro/2021-07-27-kafka-as-a-message-queue-diagrams-kafka-consumers-partitions.CAkxMcGf_PwMKm.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;As we can see on the diagram, consumers automatically assign between partitions while running.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Warn: If we have more consumers than partitions, some will idle.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Commit message&lt;/h3&gt;
&lt;p&gt;When choosing a message queue pattern, we expect to work with messages individually. We hope to commit messages individually.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Commit messages unordered&quot; width=&quot;520&quot; height=&quot;449&quot; src=&quot;https://safigo.dev/_astro/2021-07-27-kafka-as-a-message-queue-diagrams-commit-messages-unordered.BwTSryLY_Zr6qrM.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the diagram above, we can see the example of our expectations. Of course, if we do not commit some individual message, we will receive it soon. Still it will not stop processing the following messages.&lt;/p&gt;
&lt;p&gt;As we discussed, Kafka does not provide an API to work with messages individually, so we will shift our pointer of reading messages.
If we skip one message and do not want to commit it, we cannot move forward, and we need to wait until this message is processed or ignored to shift our pointer and move forward to the next batch.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Shift pointer&quot; width=&quot;497&quot; height=&quot;449&quot; src=&quot;https://safigo.dev/_astro/2021-07-27-kafka-as-a-message-queue-diagrams-shift-pointer.XK-90fmc_1uue3r.svg&quot; style=&quot;max-width:100%;height:auto&quot;&gt;&lt;/p&gt;
&lt;p&gt;Following the diagram, we can see that we have to process all messages in any way if we want to move forward.&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Warn: Kafka will not solve our individual message processing task. We have to think about a use case when a message cannot be processed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Kafka is a powerful tool for message processing, but it has some limitations as with any other tool.
It can solve a task with billions of messages, and it’s a fast solution. Moreover, it’s a solution with fault-tolerance out of the box. Unfortunately, however, we have to pay for these great features by increased complexity.&lt;/p&gt;
&lt;p&gt;When we choose Kafka for the message queue task, instead of, for example, RabbitMQ, let’s remember about limitations and architecture decisions to cover edge cases in our code itself to make our product the best.&lt;/p&gt;
&lt;p&gt;The main point I would like to highlight one more time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remember about limitations with partitions&lt;/li&gt;
&lt;li&gt;Do not forget that you cannot commit individual messages&lt;/li&gt;
&lt;li&gt;Do not forget to commit all messages to avoid sticking in a queue&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope this article will help someone avoid the main mistakes while working with Kafka.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://kafka.apache.org/documentation/#intro_concepts_and_terms&quot;&gt;The main concepts of Kafka&lt;/a&gt;. I did not find a direct link to Kafka documentation that explains only the partitions part. &lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fnref-main_concepts&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://kafka.apache.org/documentation/streams/&quot;&gt;Kafka Streams&lt;/a&gt; is a solution to run code on the data side to speed up processing. I’d tell it to seem to be stored procedures from SQL. &lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fnref-kafka_streams&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It requires a message key to specify a partition. Usually, the client will provide some UUIDv4 by default, ignoring it. &lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fnref-producer&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A consumer can avoid &lt;em&gt;group id&lt;/em&gt;, if it will subscribe to specific partition. But it’s not our case. &lt;a href=&quot;https://safigo.dev/posts/2021-07-27-kafka-as-a-message-queue/#user-content-fnref-consumer_group_id_partitions&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>kafka</category><category>message-queue</category><category>architecture</category></item><item><title>Use secure random number generators, please</title><link>https://safigo.dev/posts/2021-07-16-use-secure-random-please/</link><guid isPermaLink="true">https://safigo.dev/posts/2021-07-16-use-secure-random-please/</guid><description>Small suggestion that can safe any application.</description><pubDate>Sat, 17 Jul 2021 04:16:29 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The current article is an introductory article about the practical usage of different generators in standard libraries of other languages. It is the reason we do not explore different pseudo-random algorithms.&lt;/p&gt;
&lt;p&gt;The article tries to help avoid the most common issues of developers.&lt;/p&gt;
&lt;p&gt;If you have to use a specific random algorithm, certified algorithms, or algorithm forced by your security team or developer’s collegium (for example, some security products and products with particular regulations), just use it.&lt;/p&gt;
&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;I have seen a few real-world security issues related to the topic in projects I worked on.&lt;/p&gt;
&lt;p&gt;Some news (I remember only one the newest of them, I heard about):&lt;/p&gt;
&lt;blockquote style=&quot;margin:1rem 0;padding:0.25rem 0 0.25rem 1rem;border-left:4px solid rgba(128,128,128,0.4)&quot;&gt;
&lt;p&gt;Knowing the creation date of an account, an attacker can try to brute-force the account password with a small range of passwords (~100) and gain access to it.&lt;/p&gt;
&lt;p&gt;— donjon.ledger.com&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2021-07-16-use-secure-random-please/#user-content-fn-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;What random is&lt;/h2&gt;
&lt;p&gt;On the one hand, random is a simple entity to understand. But on the other hand, a random value - is a value that someone cannot predict.&lt;/p&gt;
&lt;p&gt;On the other hand, computer science did not solve the problem with the name “random”. All values generated by pseudo-random algorithms we name as “random”. All randomization algorithms are pseudo-random because they do not generate really random values.&lt;/p&gt;
&lt;h3&gt;Truly random number generators&lt;/h3&gt;
&lt;p&gt;“truly random” is more or less a natural random number generator. Specific devices can generate these values. These devices use several techniques for generating entropy, such as atmospheric noise, reverse bias semiconductors and beam splitting (for example - &lt;a href=&quot;https://doi.org/10.6028/NIST.SP.800-90B&quot;&gt;Recommendation for the Entropy Sources Used for Random Bit Generation&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;There is at least one service with APIs that can be used to generate “truly random” values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://api.random.org/pricing&quot;&gt;random.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pseudo-random number generators&lt;/h2&gt;
&lt;p&gt;In all languages I’ve seed before presented at least two different types of random number generators:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Pseudorandom_number_generator&quot;&gt;Pseudo random number generator&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;https://safigo.dev/posts/2021-07-16-use-secure-random-please/#user-content-fn-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. Known as PRNG&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Cryptographically-secure_pseudorandom_number_generator&quot;&gt;Cryptographically secure random number generator&lt;/a&gt;. Known as CSPRNG&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pseudo-random number generator (PRNG)&lt;/h3&gt;
&lt;p&gt;PRNG is a predictable number generator to specify custom “seed”.&lt;/p&gt;
&lt;p&gt;Seed is a value that uses as a starting value for the following random values mathematically calculated from previously generated values.&lt;/p&gt;
&lt;p&gt;It means that everyone who knows used seed can generate the same infinite sequence of numbers.&lt;/p&gt;
&lt;h4&gt;When to use&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;We need to have predictable random values, and we save seeds between generated values&lt;/li&gt;
&lt;li&gt;We write a performance-sensitive application, and we do not use random functions for sensitive data&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;When not to use&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Use this function NEVER, until you are sure you HAVE TO use it in your particular case&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Small suggestion&lt;/h4&gt;
&lt;p&gt;If you decide to use this random and you need to specify your custom seed. Use, please, something less predictable than the then-current timestamp in seconds.&lt;/p&gt;
&lt;p&gt;Possible ideas (higher is better in my opinion):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you can use some secure random algorithm, but you decided to use a faster solution, then generate seed once by secure random and use the selected algorithm after that&lt;/li&gt;
&lt;li&gt;If you cannot use secure random at all, use different unique values from your node, like the PID of an app, timestamp in nanoseconds, IP address, mac address, etc. Combine as many unique values as you can&lt;/li&gt;
&lt;li&gt;Use, at least, UNIX timestamp in nanoseconds with PID&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Cryptographically secure random number generator (CSPRNG)&lt;/h3&gt;
&lt;p&gt;CSPRNG is also a pseudo-random number generator and mathematical. Still it uses more complicated rules and algorithms to make it challenging to predict random values.&lt;/p&gt;
&lt;p&gt;These algorithms are usually suggested for “real” sensitive generated values. I’m not a security expert to contradict this statement, but I have a reason to add more rules for using secure random.&lt;/p&gt;
&lt;p&gt;Usually, software engineers are not as familiar with security (I’m as well) as we think. So when developers write some feature, they think the particular random number will not affect safety. Still, it can affect it in the future.&lt;/p&gt;
&lt;h4&gt;When not to use&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Use a basic CSPRNG provided by a programming language whenever you need random bytes. You did not decide to use the faster one&lt;/li&gt;
&lt;li&gt;Investigate more secure implementation in a language or external libraries, if you need a certified crypto-secure generator&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;When not to use&lt;/h4&gt;
&lt;p&gt;From my perspective, there are only two reasons to stop using this solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Performance issues that require to switch to something faster&lt;/li&gt;
&lt;li&gt;Platform limitations where no way to use this kind of generators&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Until developers are sure what they are doing (even better to get approval from the security team for a particular use case), I’d suggest using CSPRNG from a language.&lt;/p&gt;
&lt;p&gt;In libraries, a good way would be to provide options between different random functions and specify crypto-random generators by default.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot;&gt;&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://donjon.ledger.com/kaspersky-password-manager/&quot;&gt;First found website&lt;/a&gt;, because I remember the issue from the news &lt;a href=&quot;https://safigo.dev/posts/2021-07-16-use-secure-random-please/#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In some languages, this type of “random” is named as mathematical, for example, Golang &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;math/rand&lt;/code&gt;, JavaScript and Java &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Math.random&lt;/code&gt; &lt;a href=&quot;https://safigo.dev/posts/2021-07-16-use-secure-random-please/#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>security</category><category>random</category><category>programming</category></item><item><title>Accept header parser and matcher</title><link>https://safigo.dev/posts/2021-07-03-mime-headers/</link><guid isPermaLink="true">https://safigo.dev/posts/2021-07-03-mime-headers/</guid><description>Every REST service MUST support Accept header</description><pubDate>Sun, 04 Jul 2021 02:09:05 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;It’s not evident that the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header is an essential part of HTTP, especially REST communication.
Usually, people do not worry about the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header, either I’m.&lt;/p&gt;
&lt;p&gt;This short article will show how simple to add validation and matching to your HTTP router independently to the router and framework you use.&lt;/p&gt;
&lt;h2&gt;About Accept header&lt;/h2&gt;
&lt;p&gt;&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header is a simple list of mime types (&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;application/json&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;text/html&lt;/code&gt;, etc.) or wildcard rules (&lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;*/*&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;application/*&lt;/code&gt;, etc.) that a client supports.
In the case of the provider &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header, the client expects to respond with one of the matched mime types from the header.&lt;/p&gt;
&lt;p&gt;This header also supports additional parameters that a client can provide per a mime type.&lt;/p&gt;
&lt;p&gt;The main parameter is quality &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;q&lt;/code&gt;, that defines order of rules to choose the best option for a client, for example: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;*/*;q=0.1, application/json; q=1, application/xml; q=0.8&lt;/code&gt;.
In this example, we prefer to receive a response in JSON. If it’s not supported, return in XML; otherwise, it does not matter the response mime type.&lt;/p&gt;
&lt;p&gt;The second example is character encoding &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;charset&lt;/code&gt;. If a client sets some &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;charset&lt;/code&gt;, it expects to receive a response encoded.&lt;/p&gt;
&lt;h3&gt;Implementation notes&lt;/h3&gt;
&lt;p&gt;Following the description above. We can specify requirements for the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header parser&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Split all mime types by &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;,&lt;/code&gt; symbol;&lt;/li&gt;
&lt;li&gt;Parse mime type and params;&lt;/li&gt;
&lt;li&gt;Order mime types and rules by:
&lt;ol&gt;
&lt;li&gt;Use &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;q&lt;/code&gt; parameter to sort;&lt;/li&gt;
&lt;li&gt;More strict mime types have more priority than wildcards;&lt;/li&gt;
&lt;li&gt;More parameters have more priority.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Match supported mime types to &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; rules from the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header and find the best result for the client or server.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Creating middleware&lt;/h2&gt;
&lt;p&gt;Your router/framework can support this feature out of the box. If possible, do not spend time implementing your solution.
However, read the article in case of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You disagree with an implementation in your framework;&lt;/li&gt;
&lt;li&gt;You need to implement support of &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header by yourself;&lt;/li&gt;
&lt;li&gt;You want to discover more about &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header supporting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;We will use &lt;a href=&quot;https://github.com/safigo/mimeheader&quot;&gt;mimeheader&lt;/a&gt; library to parse and match mime types;&lt;/li&gt;
&lt;li&gt;Our middleware will implement &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;http.HandlerFunc&lt;/code&gt; type;&lt;/li&gt;
&lt;li&gt;It’s ONLY for learning purposes, do not use it in real projects AS IS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Header parsing explanation&lt;/h3&gt;
&lt;p&gt;In this block, we will review the main part of an example:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;header&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Header&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Parse Accept header to build needed rules for matching.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ah&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; mimeheader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ParseAcceptHeader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;header&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// We do not need default mime type.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mh&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mtype&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ah&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Negotiate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;acceptMimeTypes&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;  // If not matched accept mim type, return 406.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  rw&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WriteHeader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StatusNotAcceptable&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Add matched mime type to context.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WithValue&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;resp_content_type&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mtype&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Add charset, if exists.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;chs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; mh&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Params&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;charset&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ok&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  ctx&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WithValue&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;resp_charset&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;chs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Actually the main magic happenes in two lines of code:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// Parse Accept header to build needed rules for matching.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ah&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; mimeheader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ParseAcceptHeader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;header&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;// We do not need default mime type.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mh&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mtype&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ah&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Negotiate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;acceptMimeTypes&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s precisely the whole code needed to parse and match mime types. Other logic is related to the processing of retrieved data.&lt;/p&gt;
&lt;h3&gt;http/net middleware for http.HandleFunc&lt;/h3&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;github.com/safigo/mimeheader&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;NewServeMux&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HandleFunc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;acceptHeaderMiddleware&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;application/json&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;text/html&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;})(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;handlerTestFunc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;:8080&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  log&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Fatalln&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; acceptHeaderMiddleware&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;acceptMimeTypes&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HandlerFunc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HandlerFunc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; return&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HandlerFunc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;HandlerFunc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ResponseWriter&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   header&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Header&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   ah&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; mimeheader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ParseAcceptHeader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;header&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;   // We do not need default mime type.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   mh&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mtype&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ah&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Negotiate&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;acceptMimeTypes&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;   if&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;    // If not matched accept mim type, return 406.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    rw&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WriteHeader&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;StatusNotAcceptable&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;    return&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;   // Add matched mime type to context.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   ctx&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WithValue&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;resp_content_type&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mtype&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;   // Add charset, if set&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   chs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ok&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; mh&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;Params&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;charset&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;   if&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; ok&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;    ctx&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WithValue&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;resp_charset&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;chs&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;   // New requet from new context.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;   rc&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;WithContext&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;   // Call next middleware or handler.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;   next&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; handlerTestFunc&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;rw&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;ResponseWriter&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; mtype&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;resp_content_type&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).(&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; :=&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;resp_charset&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;).(&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; rw&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;Write&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;mtype&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Responses&lt;/h3&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;http&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http://localhost:8080/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; text/*; q=0.9,application/json; q=1;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##HTTP/1.1 200 OK&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Date: Sat, 03 Jul 2021 23:55:41 GMT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Length: 17&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Type: text/plain; charset=utf-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##application/json:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;####&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http://localhost:8080/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; text/*; q=1,application/json; q=1; charset=utf-8bm;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##HTTP/1.1 200 OK&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Date: Sat, 03 Jul 2021 23:56:14 GMT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Length: 24&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Type: text/plain; charset=utf-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##application/json:utf-8bm&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;####&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http://localhost:8080/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; text/html; charset=utf-8; q=1,application/*; q=1; charset=cp1251;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##HTTP/1.1 200 OK&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Date: Sat, 03 Jul 2021 23:54:20 GMT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Length: 14&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Type: text/plain; charset=utf-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##text/html:utf-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;####&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http://localhost:8080/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; text/*; q=1,application/*; q=0.9;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##HTTP/1.1 200 OK&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Date: Sat, 03 Jul 2021 23:56:33 GMT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Length: 10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##Content-Type: text/plain; charset=utf-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;##text/html:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;####&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; http://localhost:8080/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2B5581&quot;&gt; text/plain; q=1,application/xml; q=1;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;## HTTP/1.1 406 Not Acceptable&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;## Date: Sat, 03 Jul 2021 19:17:28 GMT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;## Content-Length: 0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#C2C3C5&quot;&gt;## Connection: close&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Let’s not forget about the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header even if this feature is not implemented in the current framework.&lt;/p&gt;
&lt;p&gt;If you use Golang and want to work with the &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;Accept&lt;/code&gt; header or mime types in general, you could try &lt;a href=&quot;https://github.com/safigo/mimeheader&quot;&gt;mimeheader&lt;/a&gt; library. I believe it will help with the task.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>http</category><category>mime-headers</category></item><item><title>Quick review of the most popular ways to implement flags</title><link>https://safigo.dev/posts/2021-01-03-binary-flags/</link><guid isPermaLink="true">https://safigo.dev/posts/2021-01-03-binary-flags/</guid><description>Quick introduction to different type of flags with pros and cons</description><pubDate>Mon, 04 Jan 2021 02:13:42 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;There are many ways to store flags and use them for communication between &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;client &amp;#x3C;-&gt; backend service&lt;/code&gt; or &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;service &amp;#x3C;-&gt; service&lt;/code&gt;. In the article, we will review the most popular options and try to help to choose the correct way for the next project.&lt;/p&gt;
&lt;p&gt;The most popular ways to work with flags are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Store in separate &lt;a href=&quot;https://en.wikipedia.org/wiki/Column_(database)&quot;&gt;column in DB&lt;/a&gt; or separate &lt;a href=&quot;https://en.wikipedia.org/wiki/Property_(programming)&quot;&gt;property in a class/struct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Store as an &lt;a href=&quot;https://en.wikipedia.org/wiki/Array_data_structure&quot;&gt;array&lt;/a&gt; or in a &lt;a href=&quot;https://en.wikipedia.org/wiki/Set_(abstract_data_type)&quot;&gt;set&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Store as binary data in a variable&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Options&lt;/h2&gt;
&lt;h3&gt;Separate field&lt;/h3&gt;
&lt;p&gt;It means we will create a separate column in DB for each flag.&lt;/p&gt;
&lt;h4&gt;DB Example&lt;/h4&gt;
&lt;p&gt;In an example, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;is_new&lt;/code&gt; will be a flag.&lt;/p&gt;




















&lt;table style=&quot;border-collapse:collapse;width:100%;margin:1rem 0&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;id&lt;/th&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;username&lt;/th&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;is_new&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;test1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;true&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;test2&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;false&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;JSON Example&lt;/h4&gt;
&lt;p&gt;In a code or a NoSQL database representation will be:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;username&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test1&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;is_new&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;username&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test2&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;is_new&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Simple to read&lt;/li&gt;
&lt;li&gt;Simple to understand&lt;/li&gt;
&lt;li&gt;Self-documented&lt;/li&gt;
&lt;li&gt;In a code, it can represent as typed properties&lt;/li&gt;
&lt;li&gt;Simple to convert between different representations, like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;struct/class -&gt; JSON -&gt; protobuf -&gt; MsgPack -&gt; DB row -&gt; struct/class&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Simple to use in search and aggregation requests in DB (for example by &lt;a href=&quot;https://en.wikipedia.org/wiki/SQL&quot;&gt;SQL&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Can be updated in DB in parallel, by &lt;a href=&quot;https://en.wikipedia.org/wiki/Update_(SQL)&quot;&gt;UPDATE query&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Takes up memory/storage space/traffic&lt;/li&gt;
&lt;li&gt;Could be expensive in development or risky to remove in case of dynamically typed languages&lt;/li&gt;
&lt;li&gt;Could be expensive in development to add or remove or update in case of microservice architecture&lt;/li&gt;
&lt;li&gt;Could be expensive in development to remove from &lt;a href=&quot;https://en.wikipedia.org/wiki/Column_(database)&quot;&gt;DB as a column&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Use Cases&lt;/h4&gt;
&lt;p&gt;In my opinion, before using this approach, we should answer “yes” for all listed options in the &lt;em&gt;checklist&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I agree to add and remove columns in your database (or add fields to the NoSQL database)?&lt;/li&gt;
&lt;li&gt;I understand it could take up resources in DB will be used&lt;/li&gt;
&lt;li&gt;I do not have memory and traffic sensitive clients or services&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Store In Array&lt;/h3&gt;
&lt;p&gt;In the current implementation, we will store all flags in plain names.&lt;/p&gt;
&lt;h4&gt;DB Example&lt;/h4&gt;
&lt;p&gt;In a DB, we are going to store values in a separate table as &lt;a href=&quot;https://en.wikipedia.org/wiki/One-to-many_(data_model)&quot;&gt;one to many relationships&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Table &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;user&lt;/code&gt;:&lt;/p&gt;

















&lt;table style=&quot;border-collapse:collapse;width:100%;margin:1rem 0&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;id&lt;/th&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;username&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;test1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;test2&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Table &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;user_flag&lt;/code&gt;&lt;/p&gt;




















&lt;table style=&quot;border-collapse:collapse;width:100%;margin:1rem 0&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;id&lt;/th&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;user_id&lt;/th&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;flag&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;is_new&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;is_test&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Every &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;user_flag&lt;/code&gt; row is linked to a row in &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;user&lt;/code&gt; table by &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;user_id&lt;/code&gt; field.
It can be optimized to not store the flag as a string, but it is not so important in our current topic.&lt;/p&gt;
&lt;h4&gt;JSON Example&lt;/h4&gt;
&lt;p&gt;In a code or a NoSQL database representation will be:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;username&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test1&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;flags&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;			&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;is_new&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;			&quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;is_test&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;		]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;username&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test2&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;flags&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Simple to read&lt;/li&gt;
&lt;li&gt;Simple to understand&lt;/li&gt;
&lt;li&gt;Self-documented&lt;/li&gt;
&lt;li&gt;Could be dynamically extended in a code (does not need to update code to add new flag)&lt;/li&gt;
&lt;li&gt;Simple to convert between different representations, like &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;struct/class -&gt; JSON -&gt; protobuf -&gt; MsgPack -&gt; DB row -&gt; struct/class&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pretty simple to use in search and aggregation requests in DB (for example by &lt;a href=&quot;https://en.wikipedia.org/wiki/SQL&quot;&gt;SQL&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Can be updated in DB in parallel, by &lt;a href=&quot;https://en.wikipedia.org/wiki/Insert_(SQL)&quot;&gt;INSERT query&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Delete_(SQL)&quot;&gt;DELETE query&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Takes up memory/storage space/traffic&lt;/li&gt;
&lt;li&gt;Need to write additional code for &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;set&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;unset&lt;/code&gt; and &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;find&lt;/code&gt; functions&lt;/li&gt;
&lt;li&gt;Could affect different limitation in case of many flags&lt;/li&gt;
&lt;li&gt;Could affect performance, especially on a client-side&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;User Cases&lt;/h4&gt;
&lt;p&gt;In my opinion, before using this approach, we should answer “yes” for all listed options in the &lt;em&gt;checklist&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I do not have performance and memory and traffic sensitive clients or services&lt;/li&gt;
&lt;li&gt;I understand it could take up resources on all sides it would be used&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Store In Bitmask&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Mask_(computing)&quot;&gt;Bitmask&lt;/a&gt; is a way when we use &lt;a href=&quot;https://en.wikipedia.org/wiki/Bitwise_operation&quot;&gt;bitwise operations&lt;/a&gt; to get access to specific &lt;em&gt;flag&lt;/em&gt;. Every flag stores in binary data in memory, for example it can be stored in: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;byte&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;short&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;int&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;uint&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;long&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;[]byte&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;[]short&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;map[int]byte&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;Simply read &lt;a href=&quot;https://github.com/safigo/binflags/blob/main/README.md&quot;&gt;README.md from binflags library&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;DB Example&lt;/h4&gt;
&lt;p&gt;In DB, we can store bitmask in various types, like: &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;TINYINT&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;SMALLINT&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;MEDIUMINT&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;INT&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;BIGINT&lt;/code&gt;, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;BLOB&lt;/code&gt; types.&lt;/p&gt;




















&lt;table style=&quot;border-collapse:collapse;width:100%;margin:1rem 0&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;id&lt;/th&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;username&lt;/th&gt;&lt;th style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem;text-align:left&quot;&gt;flags&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;test1&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;test2&lt;/td&gt;&lt;td style=&quot;border:1px solid rgba(128,128,128,0.4);padding:0.4rem 0.6rem&quot;&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;In the current example, &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;flags&lt;/code&gt; field has the type &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;INT&lt;/code&gt;, and the first bit is &lt;code style=&quot;background-color:rgba(128,128,128,0.15);padding:0.1em 0.35em;border-radius:4px&quot;&gt;is_new&lt;/code&gt; flag.&lt;/p&gt;
&lt;h4&gt;JSON Example&lt;/h4&gt;
&lt;p&gt;In a code or a NoSQL database representation will be:&lt;/p&gt;
&lt;pre style=&quot;color:#24292eff;background-color:#ffffff;overflow-x:auto;padding:1rem;border-radius:6px;white-space:pre;border:1px solid rgba(128,128,128,0.35);font-size:0.9em;line-height:1.5&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;username&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test1&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;flags&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;username&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;test2&lt;/span&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#D32F2F&quot;&gt;		&quot;flags&quot;&lt;/span&gt;&lt;span style=&quot;color:#212121&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#1976D2&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span style=&quot;color:#24292EFF&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Simple to understand&lt;/li&gt;
&lt;li&gt;The fastest implementation for all operations with flags&lt;/li&gt;
&lt;li&gt;Do not take up additional memory and traffic resources (always only 1 bit per flag)&lt;/li&gt;
&lt;li&gt;Can be used in a search by DB (but cannot be efficiently used indexes)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;In some cases, flags cannot be updated in parallel&lt;/li&gt;
&lt;li&gt;Cannot search flags by index&lt;/li&gt;
&lt;li&gt;Have to be documented (name to bit mapping)&lt;/li&gt;
&lt;li&gt;Should be explained for some people&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Use Cases&lt;/h4&gt;
&lt;p&gt;In my opinion, before using this approach, we should answer “yes” for all listed options in the &lt;em&gt;checklist&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I want to save memory/traffic/processor resources&lt;/li&gt;
&lt;li&gt;I understand all limitations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As we can see, as usual, we do not have a &lt;em&gt;silver bullet&lt;/em&gt; for all use cases and systems. But the provided list of implementations can help find the best solution for a specific project.&lt;/p&gt;
&lt;p&gt;If you want to use the most efficient option in &lt;a href=&quot;https://golang.org&quot;&gt;Go&lt;/a&gt;, I would suggest checking &lt;a href=&quot;https://github.com/safigo/binflags&quot;&gt;Go implementation of binary flags for various types&lt;/a&gt;.&lt;/p&gt;</content:encoded><dc:creator>Anton Ohorodnyk</dc:creator><category>go</category><category>binary-flags</category><category>architecture</category></item></channel></rss>