<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shiraaz Moollatjie</title>
    <description>The latest articles on Forem by Shiraaz Moollatjie (@shiraazm).</description>
    <link>https://forem.com/shiraazm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F120766%2F1c6928fc-c594-4bcd-8409-402bce38fff0.jpg</url>
      <title>Forem: Shiraaz Moollatjie</title>
      <link>https://forem.com/shiraazm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shiraazm"/>
    <language>en</language>
    <item>
      <title>A journey with good old base64</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Tue, 06 Oct 2020 11:35:08 +0000</pubDate>
      <link>https://forem.com/shiraazm/a-journey-with-good-old-base64-39j2</link>
      <guid>https://forem.com/shiraazm/a-journey-with-good-old-base64-39j2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I did some work around base64 in go. I found it pretty interesting and thought that it would make a nice article to write about&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  What is base64?
&lt;/h1&gt;

&lt;p&gt;Base64 is a binary to text encoding scheme that represents binary data in plain ASCII format. It's designed to give your application a way of transferring binary data across text protocols. The technical specification for base64 can be found at &lt;a href="https://tools.ietf.org/html/rfc4648"&gt;RFC 4648&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Common use cases
&lt;/h1&gt;

&lt;p&gt;The most common use cases for base64 are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embedding images in html pages. The idea is to reduce the number of server roundtrips made for your website as well as reduce the number of dependencies on your web page&lt;/li&gt;
&lt;li&gt;Returning binary data (such as images) in JSON or XML apis&lt;/li&gt;
&lt;li&gt;When using HTTP basic authentication, the username/password combination is encoded into base64 format&lt;/li&gt;
&lt;li&gt;Saving binary files into your database if a BLOB/CLOB data type is not supported&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Leave a comment if you used base64 for anything!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Let's encode in go
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;You can follow the examples on your local pc&lt;/strong&gt; using the associated &lt;a href="https://play.golang.org/p/FqbGUkK4M8w"&gt;go playground&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What can we use?
&lt;/h2&gt;

&lt;p&gt;Go has base64 support available under the &lt;code&gt;encoding/base64&lt;/code&gt; &lt;a href="http://package.It"&gt;package.&lt;/a&gt; It is largely driven by an &lt;code&gt;Encoding&lt;/code&gt; type with four default encodings available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;StdEncoding&lt;/li&gt;
&lt;li&gt;RawStdEncoding&lt;/li&gt;
&lt;li&gt;URLEncoding&lt;/li&gt;
&lt;li&gt;RawURLEncoding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For this post, I will not go into the &lt;code&gt;URLEncoding&lt;/code&gt; and &lt;code&gt;RawURLEncoding&lt;/code&gt; types.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding examples - Simple encoding &amp;amp; decoding
&lt;/h2&gt;

&lt;p&gt;We'll start our examples with some base text that we want to encode:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Programs must be written for people to read, and only incidentally for machines to execute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can copy &amp;amp; paste this into an &lt;a href="https://www.base64encode.org/"&gt;online base64 encoder/decoder&lt;/a&gt; for external verification. To encode some text, we can simply do the following:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/base64"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Programs must be written for people to read, and only incidentally for machines to execute."&lt;/span&gt;

    &lt;span class="n"&gt;encStd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;encRawStd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RawStdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;decStd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DecodeString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"code better for blog posts: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;decRawStd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RawStdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DecodeString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encRawStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"code better for blog posts: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"original string:     %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"encoded  string:     %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"raw encoded  string: %s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encRawStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"decoded  string:     %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decRawStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"raw decoded  string: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This gives you the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;Programs&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;written&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;incidentally&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;machines&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;encoded&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;UHJvZ3JhbXMgbXVzdCBiZSB3cml0dGVuIGZvciBwZW9wbGUgdG8gcmVhZCwgYW5kIG9ubHkgaW5jaWRlbnRhbGx5IGZvciBtYWNoaW5lcyB0byBleGVjdXRlLg&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;
&lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="n"&gt;encoded&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UHJvZ3JhbXMgbXVzdCBiZSB3cml0dGVuIGZvciBwZW9wbGUgdG8gcmVhZCwgYW5kIG9ubHkgaW5jaWRlbnRhbGx5IGZvciBtYWNoaW5lcyB0byBleGVjdXRlLg&lt;/span&gt;

&lt;span class="n"&gt;decoded&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;Programs&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;written&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;incidentally&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;machines&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="n"&gt;decoded&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Programs&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;written&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;incidentally&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;machines&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Comments
&lt;/h2&gt;

&lt;p&gt;There is a subtle difference between &lt;code&gt;RawStdEncoding&lt;/code&gt; and &lt;code&gt;StdEncoding&lt;/code&gt; and that would be the presence of padding characters. The &lt;code&gt;StdEcoding&lt;/code&gt; type includes padding characters in its output. The default padding character for base64 is &lt;code&gt;=&lt;/code&gt; and it is customizable.&lt;/p&gt;

&lt;p&gt;The two encoded formats are also not interchangeable. So adding these snippets will cause errors during decoding (and encoding):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;decStd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DecodeString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encRawStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cannot use a raw encoded base64 string for standard decoding: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;decRawStd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RawStdEncoding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DecodeString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encStd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cannot use a standard encoded base64 string for raw decoding: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Let's do some slightly more complex encoding
&lt;/h1&gt;

&lt;p&gt;In this next example, let us try to base64 encode an image. This program will write the go logo to stdout in base64 format.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/base64"&lt;/span&gt;
    &lt;span class="s"&gt;"io/ioutil"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Encode a base64 image. Using a URL because it's simpler than using a file.&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://golang.org/lib/godoc/images/go-logo-blue.svg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"code better for blog posts: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ioutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"code better for blog posts: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;encoder&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StdEncoding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This yields the following output (viewable on an &lt;a href="https://base64.guru/converter/decode/image"&gt;online base64 decoder&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;PHN2ZyBoZWlnaHQ9Ijc4IiB2aWV3Qm94PSIwIDAgMjA3IDc4IiB3aWR0aD0iMjA3IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxnIGZpbGw9IiMwMGFjZDciIGZpbGwtcnVsZT0iZXZlbm9kZCI&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;PHBhdGggZD0ibTE2LjIgMjQuMWMtLjQgMC0uNS0uMi0uMy0uNWwyLjEtMi43Yy4yLS4zLjctLjUgMS4xLS41aDM1LjdjLjQgMCAuNS4zLjMuNmwtMS43IDIuNmMtLjIuMy0uNy42LTEgLjZ6Ii8&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;PHBhdGggZD0ibTEuMSAzMy4zYy0uNCAwLS41LS4yLS4zLS41bDIuMS0yLjdjLjItLjMuNy0uNSAxLjEtLjVoNDUuNmMuNCAwIC42LjMuNS42bC0uOCAyLjRjLS4xLjQtLjUuNi0uOS42eiIvPjxwYXRoIGQ9Im0yNS4zIDQyLjVjLS40IDAtLjUtLjMtLjMtLjZsMS40LTIuNWMuMi0uMy42LS42IDEtLjZoMjBjLjQgMCAuNi4zLjYuN2wtLjIgMi40YzAgLjQtLjQuNy0uNy43eiIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU1KSI&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;PHBhdGggZD0ibTc0LjEgMjIuM2MtNi4zIDEuNi0xMC42IDIuOC0xNi44IDQuNC0xLjUuNC0xLjYuNS0yLjktMS0xLjUtMS43LTIuNi0yLjgtNC43LTMuOC02LjMtMy4xLTEyLjQtMi4yLTE4LjEgMS41LTYuOCA0LjQtMTAuMyAxMC45LTEwLjIgMTkgLjEgOCA1LjYgMTQuNiAxMy41IDE1LjcgNi44LjkgMTIuNS0xLjUgMTctNi42LjktMS4xIDEuNy0yLjMgMi43LTMuNy0zLjYgMC04LjEgMC0xOS4zIDAtMi4xIDAtMi42LTEuMy0xLjktMyAxLjMtMy4xIDMuNy04LjMgNS4xLTEwLjkuMy0uNiAxLTEuNiAyLjUtMS42aDM2LjRjLS4yIDIuNy0uMiA1LjQtLjYgOC4xLTEuMSA3LjItMy44IDEzLjgtOC4yIDE5LjYtNy4yIDkuNS0xNi42IDE1LjQtMjguNSAxNy05LjggMS4zLTE4LjktLjYtMjYuOS02LjYtNy40LTUuNi0xMS42LTEzLTEyLjctMjIuMi0xLjMtMTAuOSAxLjktMjAuNyA4LjUtMjkuMyA3LjEtOS4zIDE2LjUtMTUuMiAyOC0xNy4zIDkuNC0xLjcgMTguNC0uNiAyNi41IDQuOSA1LjMgMy41IDkuMSA4LjMgMTEuNiAxNC4xLjYuOS4yIDEuNC0xIDEuN3oiLz48cGF0aCBkPSJtMTA3LjIgNzcuNmMtOS4xLS4yLTE3LjQtMi44LTI0LjQtOC44LTUuOS01LjEtOS42LTExLjYtMTAuOC0xOS4zLTEuOC0xMS4zIDEuMy0yMS4zIDguMS0zMC4yIDcuMy05LjYgMTYuMS0xNC42IDI4LTE2LjcgMTAuMi0xLjggMTkuOC0uOCAyOC41IDUuMSA3LjkgNS40IDEyLjggMTIuNyAxNC4xIDIyLjMgMS43IDEzLjUtMi4yIDI0LjUtMTEuNSAzMy45LTYuNiA2LjctMTQuNyAxMC45LTI0IDEyLjgtMi43LjUtNS40LjYtOCAuOXptMjMuOC00MC40Yy0uMS0xLjMtLjEtMi4zLS4zLTMuMy0xLjgtOS45LTEwLjktMTUuNS0yMC40LTEzLjMtOS4zIDIuMS0xNS4zIDgtMTcuNSAxNy40LTEuOCA3LjggMiAxNS43IDkuMiAxOC45IDUuNSAyLjQgMTEgMi4xIDE2LjMtLjYgNy45LTQuMSAxMi4yLTEwLjUgMTIuNy0xOS4xeiIgZmlsbC1ydWxlPSJub256ZXJvIi8&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;PC9nPjwvZz48L3N2Zz4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  When base64 is not recommended
&lt;/h1&gt;

&lt;p&gt;Base64 is of course not a silver bullet. There are cases where base64 is not recommended.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not use base64 for storing passwords
&lt;/h2&gt;

&lt;p&gt;It is highly recommended to NOT use abse64 for storing passwords. It seems easy enough to encode data into a format that's hard to read for humans. However, base64 is birectional, so whatever is encoded can be easily decoded. This highlights an important distinction that base64 is an &lt;strong&gt;encoding&lt;/strong&gt; scheme, not an &lt;strong&gt;encryption&lt;/strong&gt; scheme.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not replace all your website images with base64 variants
&lt;/h2&gt;

&lt;p&gt;While it is possible to convert your images to base64, it comes with the following tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The base64 version of your image is larger (heuristically ~30% larger)&lt;/li&gt;
&lt;li&gt;You lose the ability to cache images on the client side&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;In this post, we wrote some simple go programs to show off its capabilities. These snippets could be used as the base of your own applications.&lt;/p&gt;

&lt;p&gt;Base64 is indeed a neat piece of computer science research. However, it is not a silver bullet and there are pros and cons when using the encoding in your application. Always use the best tool for the job.&lt;/p&gt;

</description>
      <category>go</category>
      <category>base64</category>
    </item>
    <item>
      <title>Gophorem - A go API client for forem</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Mon, 17 Aug 2020 19:39:59 +0000</pubDate>
      <link>https://forem.com/shiraazm/gophorem-a-go-api-client-for-forem-3m62</link>
      <guid>https://forem.com/shiraazm/gophorem-a-go-api-client-for-forem-3m62</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a post about gophorem. Where gophers and forem meet to build communities.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;I love to use go and I love the idea of &lt;code&gt;forem&lt;/code&gt;&lt;/strong&gt;. I also noticed that &lt;code&gt;forem&lt;/code&gt; &lt;br&gt;
does not have any go client support. So I wrote one and it's called &lt;code&gt;gophorem&lt;/code&gt;. It's awesome.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ShiraazMoollatjie"&gt;
        ShiraazMoollatjie
      &lt;/a&gt; / &lt;a href="https://github.com/ShiraazMoollatjie/gophorem"&gt;
        gophorem
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Where gophers and forem meet to build communities
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  🤔 What is gophorem
&lt;/h1&gt;

&lt;p&gt;In reality, it's a REST API client for the entire forem API written in go. I &lt;br&gt;
prefer to call it &lt;strong&gt;the place where gophers and forem meet up to build communities&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  🤷 What can you do with it?
&lt;/h1&gt;

&lt;p&gt;Many things! Soon I'll be posting about how I used gophorem to do some data &lt;br&gt;
visualization with dev.to data. Essentially, &lt;strong&gt;the entire forem API is supported&lt;br&gt;
by gophorem&lt;/strong&gt;. This means that you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use this on ANY forem&lt;/li&gt;
&lt;li&gt;Manage articles&lt;/li&gt;
&lt;li&gt;Manage listings&lt;/li&gt;
&lt;li&gt;Manage webhooks&lt;/li&gt;
&lt;li&gt;List podcasts, video articles&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  ⌨️ How do you use it?
&lt;/h1&gt;

&lt;p&gt;Gophorem is pretty simple to use. There are also &lt;strong&gt;examples to help you&lt;/strong&gt; get started too.&lt;br&gt;
This is an example to retrieve the latest go articles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gophorem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDevtoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gophorem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithAPIKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MY_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Retrieve all the go articles.&lt;/span&gt;
    &lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gophorem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Arguments&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"tag"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong: %+v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All Articles: %+v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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



&lt;h1&gt;
  
  
  🌧️ It supports streaming too!
&lt;/h1&gt;

&lt;p&gt;It's also possible to &lt;strong&gt;stream articles&lt;/strong&gt; with this package. This makes it &lt;br&gt;
useful for certain use cases. It's &lt;strong&gt;still a work in progress&lt;/strong&gt;, but the idea is &lt;br&gt;
to support all the listing endpoints as streams.&lt;/p&gt;

&lt;p&gt;This is an example (ripped from the examples folder) of how to stream all the recent go articles on dev.to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gophorem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDevtoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gophorem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithAPIKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MY_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;streamer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewStreamer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gophorem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Arguments&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"state"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"fresh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received article ID: %d, Title: %s, Username: %s URL: %s &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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



&lt;h1&gt;
  
  
  🤖 Future work and contributions
&lt;/h1&gt;

&lt;p&gt;Since the API is largely complete, I was thinking of adding the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finalize the streaming features&lt;/li&gt;
&lt;li&gt;Some rate-limiting features when querying forem servers&lt;/li&gt;
&lt;li&gt;Support oauth authentication&lt;/li&gt;
&lt;li&gt;Some showcase articles for what you're able to do. There is a lot of potential in this package&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all for now, check out the package and have a go at it. All contributions are welcome. Have fun!! &lt;/p&gt;

</description>
      <category>go</category>
      <category>forem</category>
      <category>showdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Devtogo update</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Tue, 04 Aug 2020 12:03:25 +0000</pubDate>
      <link>https://forem.com/shiraazm/devtogo-update-1f77</link>
      <guid>https://forem.com/shiraazm/devtogo-update-1f77</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;devtogo happens to be my first open-source API integration and I have a soft spot for &lt;a href="http://dev.to/"&gt;dev.to&lt;/a&gt; ♥️.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;devtogo is a Go API client library for &lt;a href="http://dev.to/"&gt;dev.to&lt;/a&gt;. I made a &lt;strong&gt;huge update&lt;/strong&gt; to this in the past week that I would like to share.&lt;/p&gt;

&lt;p&gt;But first, let me do my shameless plug. Always accepting contributions!&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ShiraazMoollatjie"&gt;
        ShiraazMoollatjie
      &lt;/a&gt; / &lt;a href="https://github.com/ShiraazMoollatjie/devtogo"&gt;
        devtogo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A REST API Wrapper for the dev.to api in go
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  Fully complete client
&lt;/h1&gt;

&lt;p&gt;The major update is that devtogo is a fully complete and &lt;strong&gt;supports 100% of the API features&lt;/strong&gt; 🎉. This means that you should now be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do everything with articles&lt;/li&gt;
&lt;li&gt;View comments&lt;/li&gt;
&lt;li&gt;View tags&lt;/li&gt;
&lt;li&gt;Create, update and view listings&lt;/li&gt;
&lt;li&gt;View podcast-episodes&lt;/li&gt;
&lt;li&gt;View your user profile information&lt;/li&gt;
&lt;li&gt;View video articles&lt;/li&gt;
&lt;li&gt;View webhooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a simple example that you can use as a base for a &lt;a href="http://dev.to/"&gt;dev.to&lt;/a&gt; scraper.&lt;br&gt;
&lt;/p&gt;

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

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

    &lt;span class="s"&gt;"github.com/ShiraazMoollatjie/devtogo"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithApiKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_API_KEY_HERE"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Defaults&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong: %+v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All Articles: %+v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Milestones
&lt;/h1&gt;

&lt;p&gt;These are &lt;strong&gt;important milestones&lt;/strong&gt; that happened in this project. It might not be reflective of a successful project, but they did hit and I feel proud of them&lt;/p&gt;

&lt;h2&gt;
  
  
  🎉 Someone contributed
&lt;/h2&gt;

&lt;p&gt;When I initially did my launch post, I received a much higher response than what I thought I'd get (more than zero LOL). Someone made a PR which is more valuable to me than the project itself.&lt;/p&gt;

&lt;p&gt;It felt great to get someone else to contribute. I started this project to learn more about go, so I appreciate it when other gophers tag along.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⭐ Engineers starred it
&lt;/h2&gt;

&lt;p&gt;Again, didn't expect this. Normally I leave my code on GitHub and at best at least one person will star it. This one got 5 stars, not much at all, but surprising to me.&lt;/p&gt;

&lt;h1&gt;
  
  
  Roadmap ahead
&lt;/h1&gt;

&lt;p&gt;Two themes are going forward that I feel needs to be done for this project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fork for forem
&lt;/h2&gt;

&lt;p&gt;The devtogo client needs to align with &lt;a href="http://dev.to/"&gt;dev.to&lt;/a&gt;'s new vision of forem. I think that with a little bit of commits, this project should be able to work on any forem based site. That is super cool!&lt;/p&gt;

&lt;h2&gt;
  
  
  Use more Go features
&lt;/h2&gt;

&lt;p&gt;devtogo is one of my first Go open source projects, and in some places it shows LOL. The idea is to use more go features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The use of contexts for HTTP calls&lt;/li&gt;
&lt;li&gt;Incorporating channels for certain use cases&lt;/li&gt;
&lt;li&gt;Maybe add optional metric tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Have more examples
&lt;/h2&gt;

&lt;p&gt;There are some pretty interesting things that you can do with the forem/dev.to api. I would want to showcase these in the future.&lt;/p&gt;

&lt;h1&gt;
  
  
  Shoutout to the &lt;a href="http://dev.to/"&gt;dev.to&lt;/a&gt; team
&lt;/h1&gt;

&lt;p&gt;A big thanks for the &lt;a href="http://dev.to/"&gt;dev.to&lt;/a&gt; team for giving me a platform to write about tech. I'm a big lurker, sometimes contributor and the community is so amazing. It always happens that when you think the platform peaked, then there's some innovation that happens which is super cool.&lt;/p&gt;

</description>
      <category>go</category>
      <category>showdev</category>
      <category>api</category>
      <category>devto</category>
    </item>
    <item>
      <title>Decent ways of dealing with bad posture during lockdown that's other than getting a good chair?</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Thu, 09 Jul 2020 22:40:30 +0000</pubDate>
      <link>https://forem.com/shiraazm/decent-ways-of-dealing-with-bad-posture-during-lockdown-that-s-other-than-getting-a-good-chair-4444</link>
      <guid>https://forem.com/shiraazm/decent-ways-of-dealing-with-bad-posture-during-lockdown-that-s-other-than-getting-a-good-chair-4444</guid>
      <description>&lt;p&gt;Been to the doctor complaining about chest pains. Thought it was coronavirus or worse, but turns out to be inflammation caused by bad posture (Yay and nay!!!).&lt;/p&gt;

&lt;p&gt;So the easy mode way to deal with this is to get a decent office chair for home. But to keep the discussion interesting, what are some other good posture tips that are beyond getting a good chair?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>watercooler</category>
      <category>ergonomics</category>
      <category>posture</category>
    </item>
    <item>
      <title>Tips for solo coronavirus contributors to help your websites and apps stand out</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Mon, 01 Jun 2020 18:55:01 +0000</pubDate>
      <link>https://forem.com/shiraazm/tips-for-solo-coronavirus-contributors-to-help-your-websites-and-apps-stand-out-14ba</link>
      <guid>https://forem.com/shiraazm/tips-for-solo-coronavirus-contributors-to-help-your-websites-and-apps-stand-out-14ba</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;This article has rants and some lessons. If you're facing a similar struggle, please comment on this post. I'm not aware of others going through the same kind of pain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the world took the coronavirus pandemic seriously, &lt;strong&gt;I wanted to contribute as an engineer&lt;/strong&gt;. Inspired by &lt;a href=""&gt;https://ncov2019.live/&lt;/a&gt;, I released two projects:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="http://coronawatcher.live"&gt;Coronawatcher.live&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A website that lets you &lt;strong&gt;compare coronavirus statistics between countries&lt;/strong&gt;. It also &lt;strong&gt;lets you compare the bitcoin price&lt;/strong&gt; to the coronavirus statistics.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="http://auntyrona.co.za"&gt;Aunty Rona&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A website for South Africa that &lt;strong&gt;makes it easier to interpret the lockdown rules.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Things that work for you, now all of a sudden work against you
&lt;/h1&gt;

&lt;p&gt;For my projects, I targeted a mix of web and mobile. &lt;strong&gt;There are some huge obstacles&lt;/strong&gt; that you encounter along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO woes
&lt;/h2&gt;

&lt;p&gt;One of the activities you do when developing a web app is to &lt;strong&gt;optimize the content for search engines&lt;/strong&gt;. Typically, a &lt;a href="https://ads.google.com/aw/keywordplanner/home?"&gt;keyword planner&lt;/a&gt; is one of the tools used for SEO optimization so that a web app can rank better on search engines. &lt;/p&gt;

&lt;p&gt;The lead time for SEO optimizations to reflect on a new site is around six months. However, I noticed something during keyword planning.&lt;br&gt;
&lt;strong&gt;Google does not allow keyword plans&lt;/strong&gt; for anything related to the coronavirus. This meant that Google was not allowing ads for "coronavirus" keywords. &lt;/p&gt;

&lt;p&gt;It may also mean that Google was censoring themed coronavirus web apps in their search engine. The implications for this are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new web app will not be able to rank on the first page after six months&lt;/li&gt;
&lt;li&gt;Websites/web apps currently on the first page are biased in some way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What annoys me is the &lt;strong&gt;possibility of censorship&lt;/strong&gt;. Web sites in this case will rank because of their timeliness and not because of the quality of content. Even though there are many fake news sites, a website is associated with fake news when it starts. This creates the impression that you are guilty until proven innocent.&lt;/p&gt;

&lt;h1&gt;
  
  
  Play and app store woes
&lt;/h1&gt;

&lt;p&gt;Mobile app stores &lt;strong&gt;will not publish a coronavirus themed application unless it is supported by another organization&lt;/strong&gt;. As proof, this is an excerpt of one of my appeals for the Aunty Rona mobile app:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example, your app currently contains references to Covid-19.&lt;br&gt;
If you are one of the following, Please submit valid proof to verify the identity of your organization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official government entities or public health organizations who developed this app. &lt;/li&gt;
&lt;li&gt;A developer commissioned to build this app by official government entities or public health organizations. &lt;/li&gt;
&lt;li&gt;An app supported/acknowledged by official government entities or public health organizations.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  The situation looks bleak. Is there a way out?
&lt;/h1&gt;

&lt;p&gt;My situation looked bleak, but there was still hope. Here are a &lt;strong&gt;few more ideas&lt;/strong&gt; that I had to try to get noticed. &lt;/p&gt;

&lt;h2&gt;
  
  
  If mobile stores are not willing to publish your app, consider turning your native app into a progressive web app (PWA)
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;progressive web app&lt;/strong&gt; is a solution for apps that cannot get published. This allows your app to be installable like a mobile app and depending on your implementation it can behave like a mobile app as well. The disadvantage is that a progressive web app will not benefit from being published on a mobile app store where users can "search" for your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using associative content to take advantage of keywords
&lt;/h2&gt;

&lt;p&gt;One of the ways to &lt;strong&gt;take advantage of keywords&lt;/strong&gt; is to combine your content with other themes. You can't get ranked with coronavirus keywords. However, if you associated the coronavirus statistics with the toilet paper price, could you then rank better with "toilet paper" instead?&lt;/p&gt;

&lt;p&gt;We were desperate and we did this to coronawatcher. We started associating the coronavirus statistics to the bitcoin price. I found the results interesting. As a teaser, there is one country that showed an inverse trend between the bitcoin price and coronavirus infections.&lt;/p&gt;

&lt;p&gt;While I am not ranking on the first page for bitcoin, website traffic did see an improvement. Additionally, the bitcoin price did increase ever since I implemented the feature. It's most likely a coincidence, but is it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Hashtags
&lt;/h2&gt;

&lt;p&gt;Instead of relying on keywords for the website, I &lt;strong&gt;used hashtags on other social media platforms&lt;/strong&gt;. These ranked better on search engines for whatever reason.&lt;/p&gt;

&lt;p&gt;As an example, I used the "#coronawatcher" hashtag for coronawatcher. These hashtags appear on the first page when you search for "coronawatcher".&lt;/p&gt;

&lt;h2&gt;
  
  
  Get social media handles early and post on them
&lt;/h2&gt;

&lt;p&gt;Create and own the Instagram, Twitter, and Facebook accounts for your website. These will help in featuring on the first page in search engines. It will also help with &lt;strong&gt;occupying more space on the first page&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As an example, the coronawatcher Facebook page features on the first page for "coronawatcher".&lt;/p&gt;

&lt;p&gt;There are other platforms that you can use like dev.to and hackernews. I did not focus on these platforms. However, &lt;strong&gt;DO NOT bother with posting on Reddit&lt;/strong&gt;. Reddit does not allow users to advertise their content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paying for ads on places other than Google
&lt;/h2&gt;

&lt;p&gt;My coworker on the coronawatcher project also &lt;strong&gt;experimented with paid advertising&lt;/strong&gt;. We ran a campaign against Facebook users. It resulted in a significant traffic spike. I was blown away with the results. I did not know that advertising was that effective.&lt;/p&gt;

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

&lt;p&gt;The projects were not as successful as I wanted it to be, but I learned a lot of things. I kept the ranting to a minimum. Sometimes I feel that too much ranting is petty. So I keep it to a minimum. In the end, I hope you enjoyed this post.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://web.dev/progressive-web-apps/"&gt;Official progressive web app site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>career</category>
      <category>beginners</category>
      <category>covid19</category>
    </item>
    <item>
      <title>What is considered a good career in tech?</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Wed, 19 Feb 2020 23:17:26 +0000</pubDate>
      <link>https://forem.com/shiraazm/what-is-considered-a-good-career-in-tech-924</link>
      <guid>https://forem.com/shiraazm/what-is-considered-a-good-career-in-tech-924</guid>
      <description>&lt;p&gt;I remembered a discussion with a friend of mine that had us talking about careers. Two questions came up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is considered a good career in tech?&lt;/li&gt;
&lt;li&gt;How do you want your career to look like when you're "done"?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I feel that it's good to think ahead and reassess this from time to time.&lt;/p&gt;

&lt;p&gt;I've seen the definition of a good career change many times on social media. From "working for a big tech company" all the way to "owning my own company" to "being an established writer/speaker/author". It varies from person to person.&lt;/p&gt;

&lt;p&gt;So two points up for discussion. Let's see what we think.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>One new language every year</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Thu, 02 Jan 2020 19:22:26 +0000</pubDate>
      <link>https://forem.com/shiraazm/one-new-language-every-year-4cbc</link>
      <guid>https://forem.com/shiraazm/one-new-language-every-year-4cbc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post talks about a point raised in &lt;code&gt;the pragmatic programmer&lt;/code&gt; book. It is to strive to learn one new language each year. We will also take a look at how this can be taken out of context and the anti patterns that comes from this. I think that with a little bit of realism, this is something that all engineers can strive for and can reap the rewards.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a short post about &lt;strong&gt;using the upcoming year&lt;/strong&gt; to learn a new language. This definition can be extended a little bit to include learning a new platform, OS or a new framework. For the rest of this post, we will just refer to a new &lt;em&gt;language&lt;/em&gt;, but it is interchangeable with platform/OS/framework.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Intent
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;intent behind learning a new language&lt;/strong&gt; stems from the &lt;a href="https://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X"&gt;Pragmatic Programmer&lt;/a&gt;. The idea is that our programming language &lt;strong&gt;implicitly teaches&lt;/strong&gt; you to solve a problem in a certain way. So by sticking with one language, we are &lt;strong&gt;narrowing our field of vision&lt;/strong&gt; with regard to solving problems. I believe it's an unintended side effect, but it exists.&lt;/p&gt;

&lt;p&gt;Learning a new programming language allows us to &lt;strong&gt;relook at existing problems&lt;/strong&gt; and approach them differently. These lessons can then be brought into our main language and we eventually become more creative and effective at problem solving.&lt;/p&gt;

&lt;h1&gt;
  
  
  Choosing something new to learn
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;way we choose&lt;/strong&gt; of learning something new is very important. Generally, we shouldn't choose something just because it's similar to our existing language. We &lt;strong&gt;do not choose&lt;/strong&gt; to learn &lt;code&gt;C#&lt;/code&gt; if our main language was &lt;code&gt;Java&lt;/code&gt; as an example. Nor do we learn &lt;code&gt;Python&lt;/code&gt; if our main language was &lt;code&gt;Javascript/Typescript&lt;/code&gt; for example. There are edge cases where a switch between similar toolsets makes sense. An example here is a &lt;code&gt;Java&lt;/code&gt; engineer that wants to learn &lt;code&gt;Unity&lt;/code&gt; has to inevitably learn &lt;code&gt;C#&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the general case, however, we want to be able to choose something that will &lt;strong&gt;force a change in our thinking&lt;/strong&gt;. A nice way to approach this is to switch to a language with a different programming paradigm. So a switch from an object oriented to a functional programming/scripting language makes sense and so on.&lt;/p&gt;

&lt;h1&gt;
  
  
  The learning hurdle
&lt;/h1&gt;

&lt;p&gt;This is the area where the &lt;strong&gt;least amount of advice&lt;/strong&gt; is given to engineers. Sure, it's nice to talk about this in theory and market about how it will improve your life. At the same time, this is where &lt;strong&gt;engineers run into the most nastiest anti-patterns&lt;/strong&gt;, so let's talk about success and failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What success looks like
&lt;/h2&gt;

&lt;p&gt;Funnily enough, &lt;strong&gt;success is subjective and is limited&lt;/strong&gt; to your availability. Let's be real for a minute, learning a new language is a huge undertaking because of the sacrifices needed to do this. Exponentially so if you're in a situation where you have responsibilities such as raising kids, looking after elderly parents or anything that takes up your time. These responsibilities are always more important.&lt;/p&gt;

&lt;p&gt;So realistically, what does success look like? It is probably best to &lt;strong&gt;take an incremental approach to success&lt;/strong&gt;. Starting with the end goal, we work our way down to the next acceptable form of success. So this is one form of a success ladder:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Have a profit yielding app in production
- Have an app in production
- Have an app that works on my local environment
- I wrote X blog posts about the language
- I can solve interview questions with the language
- I got X points on stackoverflow from answering questions
- I can write small programs with the language
- I can write hello world 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Each person will have different forms of success&lt;/strong&gt; with their new language. The main point is that &lt;strong&gt;they must be achievable.&lt;/strong&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Anti patterns for success
&lt;/h2&gt;

&lt;p&gt;There are &lt;strong&gt;two main anti patterns that plague engineers&lt;/strong&gt; when learning a new language. The one is &lt;strong&gt;setting up impossible goals&lt;/strong&gt;. The other is &lt;strong&gt;destroying your work life balance for the goal.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Sometimes engineers set the loftiest, most unachievable goals for themselves. For example, we set a single goal like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Learn node.js and use it to build a game server for a multiplayer, 
browser-based game by mid 2020.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are many problems with this goal. Does the engineer know what game they want to build? Why does it have to be done by mid 2020? Do they have experience in multiplayer game design? How do you know you're done with "learn node.js"? &lt;/p&gt;

&lt;p&gt;Always remember that &lt;strong&gt;the goal is always to change our way of thinking&lt;/strong&gt;, not to place extra burden on ourselves. The way out is to &lt;strong&gt;redo something you've already done&lt;/strong&gt; in a new language. This way, you don't have anything extra to learn and you're able to &lt;strong&gt;focus just on the language&lt;/strong&gt;. So reimplement an existing feature instead. Build up towards a small rewrite of your professional work application instead. This is much easier and more approachable than the big bang golden goal approach.&lt;/p&gt;

&lt;p&gt;The other anti pattern is actually a side effect of the golden goal. When setting such a huge goal for yourself, &lt;strong&gt;sometimes engineers put pressure on themselves&lt;/strong&gt; and pull off the big all nighters just to get the goal done. This decreases your quality of life and your main priorities suffer. Smaller goals helps you prioritise and backlog your goals. You'll also know ahead of time what's achievable and what isn't. Always remember that this is a hobbyist goal and should not decrease your quality of life nor add extra stress. If you can't finish it all, that's okay!&lt;/p&gt;

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

&lt;p&gt;We looked at how we can use the upcoming year to learn a new programming language. We had a small look into why we want to do this. We also thought about how to choose something new to learn, what success might look like and probably more importantly, the anti patterns involved in learning a new language each year. Hope you enjoyed this. All the best for the upcoming year!&lt;/p&gt;

</description>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>goluhn: A simple package for generating, calculating and verifying luhn numbers</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Thu, 21 Nov 2019 14:09:52 +0000</pubDate>
      <link>https://forem.com/shiraazm/goluhn-a-simple-library-for-generating-calculating-and-verifying-luhn-numbers-588j</link>
      <guid>https://forem.com/shiraazm/goluhn-a-simple-library-for-generating-calculating-and-verifying-luhn-numbers-588j</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This short article will introduce you to &lt;code&gt;goluhn&lt;/code&gt;, a very simple go package to apply luhn numbers to your projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  What is a luhn number
&lt;/h1&gt;

&lt;p&gt;A luhn number is &lt;strong&gt;a number whose last digit satisfies the luhn checksum formula&lt;/strong&gt;. It is named after its inventor Hans Peter Luhn. For example, in the luhn number &lt;code&gt;1111 2222 3333 4444&lt;/code&gt;, the last &lt;code&gt;4&lt;/code&gt; digit is the luhn checksum digit of the number. &lt;/p&gt;

&lt;h2&gt;
  
  
  Intended use and application
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;most popular use&lt;/strong&gt; of a luhn number is a credit card number. Every credit card number satisfies the luhn algorithm. Luhn numbers are also used for other identification methods such as &lt;code&gt;IMEI numbers&lt;/code&gt;, electricity meter numbers, various countries' ID numbers and so on.&lt;/p&gt;

&lt;p&gt;The luhn check is &lt;strong&gt;mainly designed&lt;/strong&gt; to protect against accidentally entered numbers, basically typos. It is not designed to protect against malicious checks. Therefore validation of these number is the main use case.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using &lt;code&gt;goluhn&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Using &lt;code&gt;goluhn&lt;/code&gt; is extremely simple. It exposes three functions &lt;code&gt;Validate&lt;/code&gt;, &lt;code&gt;Calculate&lt;/code&gt; and &lt;code&gt;Generate&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ShiraazMoollatjie" rel="noopener noreferrer"&gt;
        ShiraazMoollatjie
      &lt;/a&gt; / &lt;a href="https://github.com/ShiraazMoollatjie/goluhn" rel="noopener noreferrer"&gt;
        goluhn
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A package that implements the luhn algorithm for validation, calculation and generation
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;To kick things off, we start with the package import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/ShiraazMoollatjie/goluhn"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Validate
&lt;/h2&gt;

&lt;p&gt;We call the &lt;code&gt;Validate&lt;/code&gt; function to &lt;strong&gt;validate whether a provided string is a luhn number&lt;/strong&gt;. Invalid luhn strings return errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goluhn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1111222233334444"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Calculation
&lt;/h2&gt;

&lt;p&gt;This is used when we have a numeric string whose &lt;strong&gt;luhn check digit needs to be calculated&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goluhn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"111122223333444"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Check digit: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Luhn number: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will return the check digit as well as the original with the luhn digit appended to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Generate&lt;/code&gt; function will &lt;strong&gt;generate a random luhn number of a provided length&lt;/strong&gt;. This is useful for when you are generating your own numbers in your system. In the example below, we generate luhn numbers of length 16 (effectively a credit card number).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;goluhn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Luhn number: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Random Thoughts
&lt;/h1&gt;

&lt;p&gt;This project was quick and fun to implement. I decided to &lt;strong&gt;use strings over integers&lt;/strong&gt; because it is possible to generate luhn numbers for numbers that are greater than the &lt;code&gt;int64&lt;/code&gt; type (this is fun to try out actually). There are no real numeric operations that apply to luhn numbers, so this also motivated me to use strings instead. Strings also allow for zero padded prefixed numbers to be generated.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Validate&lt;/code&gt; function arguably &lt;strong&gt;could have returned a &lt;code&gt;bool, error&lt;/code&gt; result&lt;/strong&gt;. I don't really like returning that specific combination of types because either you have an error or the result of the function is free from errors which implies true. Additionally, I think that if you returned a boolean &lt;code&gt;false&lt;/code&gt; in this specific case, you're very likely to return an error too.&lt;/p&gt;

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

&lt;p&gt;In this article, we learnt how to use &lt;code&gt;goluhn&lt;/code&gt; to generate luhn numbers. We also delved a bit into some of the design decisions. As always, &lt;strong&gt;contributions are always welcomed!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Luhn_algorithm" rel="noopener noreferrer"&gt;The wikipedia entry&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>opensource</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Representing enums in go</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Wed, 13 Nov 2019 06:50:33 +0000</pubDate>
      <link>https://forem.com/shiraazm/representing-enums-in-go-21dp</link>
      <guid>https://forem.com/shiraazm/representing-enums-in-go-21dp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article will look at how to represent enums in go. It will also add some practical advice as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An enum is a datatype that consists of a set of named values. Many languages use the &lt;code&gt;enum&lt;/code&gt; keyword to represent enum types.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use &lt;code&gt;iota&lt;/code&gt; to define enums
&lt;/h1&gt;

&lt;p&gt;According to the &lt;a href="https://golang.org/ref/spec#Iota"&gt;Go specification&lt;/a&gt;, &lt;code&gt;iota&lt;/code&gt; is a keyword that &lt;strong&gt;represents successive untyped integer constants&lt;/strong&gt; as long as those constants are in the same &lt;code&gt;constant declaration&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, we can define the following set of constants from &lt;code&gt;c0 -&amp;gt; c2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;  &lt;span class="c"&gt;// c0 == 0&lt;/span&gt;
    &lt;span class="n"&gt;c1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;  &lt;span class="c"&gt;// c1 == 1&lt;/span&gt;
    &lt;span class="n"&gt;c2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;  &lt;span class="c"&gt;// c2 == 2&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can &lt;strong&gt;reduce the amount of code&lt;/strong&gt; written by removing the excess &lt;code&gt;iota&lt;/code&gt; declarations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
    &lt;span class="n"&gt;c1&lt;/span&gt;
    &lt;span class="n"&gt;c2&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;iota&lt;/code&gt; keyword also lets us define specific patterns with your constants, but in this article we are &lt;strong&gt;only focusing on &lt;code&gt;enums&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Applying this in practice
&lt;/h1&gt;

&lt;p&gt;So let us apply this in practice. We will use the example of card suites. So we define a suite of cards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Suite&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;unknown&lt;/span&gt; &lt;span class="n"&gt;Suite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
  &lt;span class="n"&gt;Spades&lt;/span&gt;
  &lt;span class="n"&gt;Hearts&lt;/span&gt;
  &lt;span class="n"&gt;Diamond&lt;/span&gt;
  &lt;span class="n"&gt;Clubs&lt;/span&gt;
  &lt;span class="n"&gt;sentinel&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Because our eyes are so sharp, you'd notice that I added two new values to this list: An &lt;code&gt;unknown&lt;/code&gt; and a &lt;code&gt;sentinel&lt;/code&gt; value. Let us work through their value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;unknown&lt;/code&gt; and &lt;code&gt;sentinel&lt;/code&gt; values
&lt;/h2&gt;

&lt;p&gt;Within go, generally we &lt;strong&gt;want our enum type to be able to support zero values&lt;/strong&gt;. This makes it easier to write idiomatic go without worrying about processing business logic for zero values. &lt;/p&gt;

&lt;p&gt;There are cases where zero values needs to be supported (e.g. for some externally defined protocol or even legacy code), but within our own application code we try to prevent it.&lt;/p&gt;

&lt;p&gt;The purpose of the &lt;code&gt;sentinel&lt;/code&gt; is to &lt;strong&gt;make it easy to iterate and validate&lt;/strong&gt; our list of enum values. It also adds to the &lt;strong&gt;maintainability of our enums&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, because &lt;code&gt;Suite&lt;/code&gt; is it's own type, we can in theory assign it any value. So let's try to validate that an integer is within our list of enums:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Suite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;sentinel&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, our &lt;strong&gt;validation code is agnostic of the specific values&lt;/strong&gt; of our suites. This means that we are able to add values to our enums as long as they appear &lt;code&gt;before&lt;/code&gt; our sentinel value.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deprecating enums?
&lt;/h1&gt;

&lt;p&gt;If your system is small, then this wouldn't really apply. However, suppose you do not want to support certain types for whatever reason. Go actually makes this very easy by using &lt;code&gt;_&lt;/code&gt; values. So let's say that we only want to use the black &lt;code&gt;Suites&lt;/code&gt;, but we need to keep the red &lt;code&gt;Suites&lt;/code&gt; for historical purposes. We simply do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Suite&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;unknown&lt;/span&gt; &lt;span class="n"&gt;Suite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
  &lt;span class="n"&gt;Spades&lt;/span&gt;
  &lt;span class="n"&gt;_&lt;/span&gt;
  &lt;span class="n"&gt;_&lt;/span&gt;
  &lt;span class="n"&gt;Clubs&lt;/span&gt;
  &lt;span class="n"&gt;sentinel&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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



&lt;p&gt;Using this way, we are &lt;strong&gt;maintaining the &lt;code&gt;Clubs&lt;/code&gt; data throughout the lifetime of our application&lt;/strong&gt;, and we will be able to &lt;strong&gt;catch all the usages&lt;/strong&gt; of the red &lt;code&gt;Suite&lt;/code&gt; values during refactoring.&lt;/p&gt;

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

&lt;p&gt;In this post we looked at how to define enums in go using the &lt;code&gt;iota&lt;/code&gt; keyword with our constants. We also recommended the use of an &lt;code&gt;unknown&lt;/code&gt; value and a &lt;code&gt;sentinel&lt;/code&gt; value to make application programming easier. We even took a look at possibly deprecating &lt;code&gt;enum&lt;/code&gt; values in our application.&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>enums</category>
    </item>
    <item>
      <title>Efficiently concatenating strings in go</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Tue, 05 Nov 2019 08:00:12 +0000</pubDate>
      <link>https://forem.com/shiraazm/efficiently-concatenating-strings-in-go-6do</link>
      <guid>https://forem.com/shiraazm/efficiently-concatenating-strings-in-go-6do</guid>
      <description>&lt;p&gt;In this article, we will look at different ways to concatenate strings in Go.&lt;/p&gt;

&lt;h1&gt;
  
  
  What happens when you concatenate strings with the &lt;code&gt;+&lt;/code&gt;operator
&lt;/h1&gt;

&lt;p&gt;Using the &lt;code&gt;+&lt;/code&gt; is &lt;strong&gt;good enough for pieces of code that are not critical&lt;/strong&gt; or when there are not many strings to join.&lt;/p&gt;

&lt;p&gt;However, when we have many strings to join (for whatever reason), then performance starts to degrade.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using &lt;code&gt;bytes.Buffer&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Using &lt;code&gt;bytes.Buffer&lt;/code&gt; is &lt;strong&gt;one of two efficient ways&lt;/strong&gt; to handle many string concatenations. We define a &lt;code&gt;bytes.Buffer&lt;/code&gt; type and append to this type until we are done with concatenation.&lt;/p&gt;

&lt;p&gt;A very simple example of &lt;code&gt;bytes.Buffer&lt;/code&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"somestring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A super long string: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Using &lt;code&gt;strings.Builder&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;From Go 1.10 a &lt;code&gt;strings.Builder&lt;/code&gt; type was added. It's &lt;strong&gt;designed for string concatenation&lt;/strong&gt; and &lt;strong&gt;minimizes memory copying&lt;/strong&gt;. This is the preferred method for implementing efficient string concatenation.&lt;/p&gt;

&lt;p&gt;A simple example of &lt;code&gt;strings.Builder&lt;/code&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Builder&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;concats&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"somestring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A super long string: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Let's measure some performance!
&lt;/h1&gt;

&lt;p&gt;In order to test the differences between the three methods, we can &lt;strong&gt;write a program that can measure some times&lt;/strong&gt; for a given concatenation count. Thereafter, we'll be able to visualize some performance.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is not meant to be a very strict performance benchmark. It's more to give an indicator on performance. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Benchmark test
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you happen to be unfamiliar with Go benchmarks, take a look at the &lt;a href="https://golang.org/pkg/testing/"&gt;testing package godoc&lt;/a&gt; for a really nice explanation on how it works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our benchmark test looks like this:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"bytes"&lt;/span&gt;
    &lt;span class="s"&gt;"strings"&lt;/span&gt;
    &lt;span class="s"&gt;"testing"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkStringConcatenation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;benchmarks&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;testFn&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;param&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Regular 50"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regularConcatentation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Regular 100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regularConcatentation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"bytes.Buffer 50"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytesBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"bytes.Buffer 100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytesBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"strings.Builder 50"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stringBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"strings.Builder 100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stringBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bm&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;benchmarks&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;bm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testFn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkRegularConcatenation40&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;regularConcatentation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkBytesBuffer40&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;bytesBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkStringBuilder40&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stringBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;bytesBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concats&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;concats&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"somestring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;regularConcatentation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concats&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;concats&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"somestring"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;stringBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;concats&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Builder&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;concats&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"somestring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;I do think that our benchmark results will be different on our individual machines. After running these benchmarks, we get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goos: darwin
goarch: amd64
pkg: concats
BenchmarkStringConcatenation/Regular_50-4             300000          4542 ns/op
BenchmarkStringConcatenation/Regular_100-4            100000         15084 ns/op
BenchmarkStringConcatenation/bytes.Buffer_50-4       1000000          1585 ns/op
BenchmarkStringConcatenation/bytes.Buffer_100-4      1000000          1561 ns/op
BenchmarkStringConcatenation/strings.Builder_50-4    2000000           733 ns/op
BenchmarkStringConcatenation/strings.Builder_100-4   2000000           735 ns/op
PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at these results, &lt;strong&gt;string concatentation is much slower than both bytes.Buffer and strings.Builder&lt;/strong&gt;. This will be &lt;strong&gt;consistent across different machines&lt;/strong&gt;. When using strings.Builder, it runs at about twice as fast as bytes.Buffer on my machine. I do think that the time differences between these two styles will vary between machines.&lt;/p&gt;

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

&lt;p&gt;In this post, we learnt about the different approaches to mass string concatenation in Go. We also managed to benchmark these techniques and briefly discussed the results.&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>strings</category>
      <category>performance</category>
    </item>
    <item>
      <title>Introducing devtogo: A wrapper for the dev.to api written in Go</title>
      <dc:creator>Shiraaz Moollatjie</dc:creator>
      <pubDate>Mon, 28 Oct 2019 09:57:28 +0000</pubDate>
      <link>https://forem.com/shiraazm/introducing-devtogo-a-wrapper-for-the-dev-to-api-written-in-go-348k</link>
      <guid>https://forem.com/shiraazm/introducing-devtogo-a-wrapper-for-the-dev-to-api-written-in-go-348k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post will introduce you to devtogo and will show you some usage examples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've been using Go as my main programming language for about six months at work. It's been very enjoyable and I always learn something new every day.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;wrote devtogo as a means for me to learn&lt;/strong&gt; how to write some good opensource Go code. It's also &lt;strong&gt;my very first opensource project&lt;/strong&gt; that I am publishing. Much of my work is sitting in private repositories, so I thought that I may as well expose this for the world to use.&lt;/p&gt;

&lt;p&gt;Try it out and contribute/interact with the Github repo.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ShiraazMoollatjie" rel="noopener noreferrer"&gt;
        ShiraazMoollatjie
      &lt;/a&gt; / &lt;a href="https://github.com/ShiraazMoollatjie/devtogo" rel="noopener noreferrer"&gt;
        devtogo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A REST API Wrapper for the dev.to api in go
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;devto-go&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://goreportcard.com/report/github.com/ShiraazMoollatjie/devtogo" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/0a99aad70fcaaa7f8b703e6788e7884a99fe001e8f4db8e62e02e3aa2d5de0b8/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f5368697261617a4d6f6f6c6c61746a69652f646576746f676f3f7374796c653d666c61742d737175617265" alt="Go Report Card"&gt;&lt;/a&gt;
&lt;a href="http://godoc.org/github.com/ShiraazMoollatjie/devtogo" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fe1188b9f0668a1e0a543e1cbcc6fb28d50a52f74d04e99407f8e6405a7132cd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f676f646f632d7265666572656e63652d626c75652e7376673f7374796c653d666c61742d737175617265" alt="Go Doc"&gt;&lt;/a&gt;
&lt;a href="https://ci.appveyor.com/project/ShiraazMoollatjie/devtogo" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c0002fe002796c2221aaae3df5cd1d1c0b8aca7065531e01a5da360d12684bed/68747470733a2f2f63692e6170707665796f722e636f6d2f6170692f70726f6a656374732f7374617475732f7169796e646b6f326b7264346c7465703f7376673d74727565" alt="Build status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;devto-go is a REST API Wrapper for the dev.to api written in go.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Usage&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Import the package into your go file:&lt;/p&gt;
&lt;div class="highlight highlight-source-go notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s"&gt;"github.com/ShiraazMoollatjie/devtogo"&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Thereafter, create a client and specify your API token:&lt;/p&gt;
&lt;div class="highlight highlight-source-go notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;cl&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;devtogo&lt;/span&gt;.&lt;span class="pl-en"&gt;NewClient&lt;/span&gt;(&lt;span class="pl-s1"&gt;devtogo&lt;/span&gt;.&lt;span class="pl-en"&gt;WithApiKey&lt;/span&gt;(&lt;span class="pl-s"&gt;"MY_API_KEY"&lt;/span&gt;))&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;It is also possible to not use an API key for anonymous operations.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Retrieving articles&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;To retrieve a list of articles, simply use the &lt;code&gt;Articles&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight highlight-source-go notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;articles&lt;/span&gt;, &lt;span class="pl-s1"&gt;err&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;cl&lt;/span&gt;.&lt;span class="pl-en"&gt;Articles&lt;/span&gt;(&lt;span class="pl-s1"&gt;devtogo&lt;/span&gt;.&lt;span class="pl-en"&gt;Defaults&lt;/span&gt;())&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;It is also possible for us to add query parameters. For example, it's useful to retrieve articles for a specific &lt;code&gt;tag&lt;/code&gt;.
The way to do this would be:&lt;/p&gt;
&lt;div class="highlight highlight-source-go notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;al&lt;/span&gt;, &lt;span class="pl-s1"&gt;err&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;cl&lt;/span&gt;.&lt;span class="pl-en"&gt;Articles&lt;/span&gt;(devtogo.&lt;span class="pl-smi"&gt;Arguments&lt;/span&gt;{
        &lt;span class="pl-s"&gt;"tag"&lt;/span&gt;: &lt;span class="pl-s"&gt;"go"&lt;/span&gt;,
    })&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;To retrieve a single article, you need to specify the &lt;code&gt;article id&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-go notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;article&lt;/span&gt;, &lt;span class="pl-s1"&gt;err&lt;/span&gt; &lt;span class="pl-c1"&gt;:=&lt;/span&gt; &lt;span class="pl-s1"&gt;client&lt;/span&gt;.&lt;span class="pl-en"&gt;GetArticle&lt;/span&gt;(&lt;span class="pl-s"&gt;"167919"&lt;/span&gt;)&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ShiraazMoollatjie/devtogo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Devtogo is an rest api wrapper&lt;/strong&gt; for the dev.to api. It can be used to publish articles or even search for articles of a specific tag. There are many usecases for using the dev.to api.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a client
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;client can be created anonymously or via credentials&lt;/strong&gt;. The only credentials supported at the moment are &lt;code&gt;api keys&lt;/code&gt; and one can can obtain them &lt;a href="https://docs.dev.to/api/#section/Authentication"&gt;by having a look at the authentication section of the api.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create a client, we simply use the &lt;code&gt;NewClient&lt;/code&gt; function and specify the api key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithApiKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MY_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Retrieving articles
&lt;/h2&gt;

&lt;p&gt;It's possible to &lt;strong&gt;retrieve either a list of articles or a single article&lt;/strong&gt;. For this post, we are going to retrieve all the articles that are tagged with &lt;code&gt;go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetArticles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Arguments&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"tag"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Retrieving articles owned by you
&lt;/h3&gt;

&lt;p&gt;If we are an authenticated user, we can &lt;strong&gt;retrieve our own list&lt;/strong&gt; of published or unpublished articles. This is &lt;strong&gt;useful&lt;/strong&gt; for obtaining a list of our drafts that we want to publish later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetMyUnpublishedArticles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Defaults&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating and updating articles
&lt;/h2&gt;

&lt;p&gt;To create an article, we use the &lt;code&gt;CreateArticle&lt;/code&gt; function. This will &lt;strong&gt;create a new article on the dev.to platform&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateArticle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateArticle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;"My new dev.to post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"go"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="n"&gt;BodyMarkdown&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"my long markdown article that is preferably read from a file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we create an article that is in a &lt;code&gt;draft&lt;/code&gt; state with a &lt;code&gt;title&lt;/code&gt;, some &lt;code&gt;tags&lt;/code&gt; and some markdown.&lt;/p&gt;

&lt;p&gt;To publish this article on create, we set the &lt;code&gt;Published&lt;/code&gt; property to true.&lt;/p&gt;

&lt;p&gt;Supposed we want to &lt;strong&gt;update this article&lt;/strong&gt; by publishing it, we simply use the &lt;code&gt;UpdateArticle&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateArticle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateArticle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;"My updates dev.to post using the API"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;BodyMarkdown&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"my new updated content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Published&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we learnt how to use the devtogo to interact with the dev.to platform using the Go programming language. We also about how to use devtogo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full example
&lt;/h2&gt;

&lt;p&gt;This is a &lt;strong&gt;full working example&lt;/strong&gt; that retrieves the latest Go articles.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"fmt"&lt;/span&gt;
  &lt;span class="s"&gt;"github.com/ShiraazMoollatjie/devtogo"&lt;/span&gt;
  &lt;span class="s"&gt;"log"&lt;/span&gt;
  &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;apiToken&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DEVTO_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;apiToken&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Set the DEVTO_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;dtgc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithApiKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiToken&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;dtgc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetArticles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devtogo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Arguments&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"tag"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Cannot retrieve articles: %+v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Title: %s, Url: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.dev.to/api"&gt;Dev.to API Documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>api</category>
      <category>devto</category>
    </item>
  </channel>
</rss>
