{"componentChunkName":"component---src-templates-tag-js","path":"/tags/go/","result":{"data":{"site":{"siteMetadata":{"title":"LoginRadius Blog"}},"allMarkdownRemark":{"totalCount":9,"edges":[{"node":{"fields":{"slug":"/engineering/why-we-rebuilt-loginradius-dot-net-core-apis-with-go/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>Currently, the LoginRadius Identity Platform processes more than 100K requests per second. As our developer and enterprise customers grow, we should be able to scale our APIs to handle staggering loads of requests per second. It won’t be surprising if our APIs have to serve a million requests per second in the future.</p>\n<p>Generally, we add more instances, CPU, or memory for supporting high request volumes. However, it has been burdening our infrastructure budget and maintenance. </p>\n<p>So, we’re focused on reducing the cost of compute capacity by improving efficiency. In this engineering update, we share our experience with a highly effective, low-risk, large-scale performance and cost optimization with Go.</p>\n<p>LoginRadius production environment consists of 30+ microservices backed by a cloud-native infrastructure. Most of these services are written in .NET and Node.js. In Q1 2021, we explored the possibilities of improving the performance of our services and optimizing costs.</p>\n<h2 id=\"how-loginradius-has-been-handling-high-rps-throughput\" style=\"position:relative;\"><a href=\"#how-loginradius-has-been-handling-high-rps-throughput\" aria-label=\"how loginradius has been handling high rps throughput permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How LoginRadius Has Been Handling High RPS Throughput?</h2>\n<p>LoginRadius tech stack consists of 30+ microservices. We have different microservices for each business service like Authentication, Web SSO, Federated SSO, etc. </p>\n<ul>\n<li>We have developed application microservices in various languages per the prevailing microservice use case.</li>\n<li>We have deployed our application in a multi-cloud environment across AWS, Azure, and Google Cloud by leveraging multiple availability zones and regions.</li>\n</ul>\n<h3 id=\"1-architecture\" style=\"position:relative;\"><a href=\"#1-architecture\" aria-label=\"1 architecture permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Architecture</h3>\n<p><strong>Core Applications:</strong> Multiple microservices instances for Authentication, Account API, Analytics API, Risk-based Authentication, Backend Jobs, Integrations, and much more, </p>\n<p><strong>Data Storage:</strong> MongoDB, Elasticsearch, Redis, and PostgreSQL clusters are used to store a range of datasets for various applications and functionalities.</p>\n<p><strong>Queues:</strong> Amazon Kinesis Data Streams, Amazon Simple Notification Service (SNS), Amazon Simple Queue Service (SQS), and Azure Queue Storage. </p>\n<p><strong>Other Services:</strong> Services for rate-limiting, bcrypt clusters, feature flags, and more.</p>\n<p><strong>Routing:</strong> AWS load balancers (ALB, NLB, and ELB from AWS) and some nodes running NGINX as a proxy.</p>\n<h3 id=\"2-availability\" style=\"position:relative;\"><a href=\"#2-availability\" aria-label=\"2 availability permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Availability</h3>\n<p>We've been utilizing a multi-cloud and multi-region architecture for years based on our and our customers’ data and privacy compliance requirements. However, as our usage (and load) grew with maintenance costs, we relied more on AWS resources.</p>\n<ul>\n<li>We are using multiple regions and multiple availability zones as per region.</li>\n<li>We are using terraform scripts to provision new environments. This infrastructure automation allowed us to quickly scale from thousands of requests per second to hundreds of thousands of requests per second.  </li>\n</ul>\n<p>This is the basic architecture of the environment in the US:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 15.4296875%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAlUlEQVQI1zWLQRKCMBAE+f8vQAX1ESggjwDxImiyF5KCQEII0d2y3MPUTHVvYJfFb865FXMcB2O09zS3bcWz1mIh6olqPX/IJtkuNuhHs8v4IYNzycKUxTmcShalkBSATyDm8MLDFI43luQ8unKk+wziAqQywaCmupN1Kx5vWbXi3slfaV5SayMHotWTZvPX0MGppvkLvYyhgHN+S1QAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Basic Architecture - US\"\n        title=\"Basic Architecture - US\"\n        src=\"/static/a923ca30b0d5aa1a50a3b7c684cb6358/01e7c/basic-architecture.png\"\n        srcset=\"/static/a923ca30b0d5aa1a50a3b7c684cb6358/01e7c/basic-architecture.png 512w\"\n        sizes=\"(max-width: 512px) 100vw, 512px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Each request is processed as follows:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 99.8046875%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAACuUlEQVQ4y41UC0/bMBDu79+kPbSJirExYBpDtAP6QEKFlQIlpfQFfVFoSGnaPNu8mjRxbCeZA4PBYILTyb4o9/m+O58vghD2Honve/UrNXksMuIkCHz8hIuHEIqQLbgn/vXqQLy8x35cO9ssS0HwwOFOMMb/gu8OKV9qawXxnJuEH/6Lwb7vAwQdCIbyyA0NCDF+HnzLGa0dcbFDYXGr9SPHrOTF467yOP7TkUm5FNNWLUdQdFE1iG067ktpE5InPa3WM/L1QfFMrDCTK9m64/UMbQDRZkVIFPlY7nw9z6wVxSqjvpR2+MNDXuBZto0wwj72/P8UjDQAOZIoaQ0HuNB1DctZ2buYT9fmNkrzqern9GmZlgMPOQC4ruvfEngQGSGIIQg8DAD41RBThasURacLTKo4aLNq4EOMIHCmtj39C1ZNZ6BMBQ1cDpW+ZIi6y6mO7bq3Vx7GGSpWuiJlTscbVC+e62xVpVRJqjHjCHUmf9oeLuyw0WQrmmov7PKzGZYWwsYiiRAlRn9kxSguURRj+73VXDdxxMcpoXQhR2TdpgWTEcwup9OcwYgWzZumDR/fzXVqyHXBEznbNiHrXmPCCt62argqE6fYEWq0XOzwh/V+lRhnPCNoEarNzyQas4nazHrlQ6wwlzqNJuuXonHTat41+pzT364338err79Tr77tv1stvfnZ3DkZRDpDfftklCmxaaq7SdHZmrh9Iguafb8ryAuVJ3BsQkGd8oqlmHBkQn0KIgBCQOZBEBjWdAoA8siTCufD/VTJUyGuJkAj3RTGOjEM2zUIONuQlg+klT32y2ZjMdONU9JSbnjB/6F9E7zWUz/vDJd2B9Fkg+hilv2a5dJlPtLsK1RnTLXF/VM23+SL5+ODtsSNw+lDaosw9j0sahaZSi1Wa/RGjatxi1WbfY3mtd8Y8VbURh2MPQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Request Processing Flow\"\n        title=\"Request Processing Flow\"\n        src=\"/static/dc681ebd4fc2e915584560a49dea681e/01e7c/request-processing-flow.png\"\n        srcset=\"/static/dc681ebd4fc2e915584560a49dea681e/01e7c/request-processing-flow.png 512w\"\n        sizes=\"(max-width: 512px) 100vw, 512px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>The above diagram shows two cloud regions — US East and US West.</p>\n<p>When requests come:</p>\n<ul>\n<li>First, our infrastructure checks the primary region's health. If health is good, all requests are served by the primary US East region with three separate availability zones. </li>\n<li>If health checks fail for the primary region, the US West region serves all the requests with three separate availability zones.</li>\n</ul>\n<p><strong>So, how do we maintain high availability?</strong></p>\n<p>Every availability zone has operating instances of all services (including databases). If one availability zone is down, we still have two availability zones.</p>\n<h3 id=\"3-scaling\" style=\"position:relative;\"><a href=\"#3-scaling\" aria-label=\"3 scaling permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Scaling</h3>\n<p>We are using a two-pronged scaling approach as scaling based on resource utilization (CPU &#x26; Memory) alone is not practical.</p>\n<ol>\n<li>Traffic-based scaling</li>\n<li>Based on CPU &#x26; Memory utilization</li>\n</ol>\n<h4 id=\"why-scaling-was-challenging\" style=\"position:relative;\"><a href=\"#why-scaling-was-challenging\" aria-label=\"why scaling was challenging permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Scaling Was Challenging?</h4>\n<p>Once, our multi-tenant application received a sudden spike in API requests — from thousands of requests to millions. Usually, adding new infrastructure to the existing pool takes around 60 seconds. And application deployment and start-up time were about 90 seconds. Plus, considering other possible delays in scaling, we can lose about 5 minutes for scaling up.</p>\n<p>Further, adding the time to gather metrics and make the scaling decision, the total delay can be ~6 minutes. This process can impact all multi-tenant customers' critical applications because user authentication and authorization are essential.</p>\n<p>We keep <em>Scaling Buffers</em> to support this kind of scenario.</p>\n<blockquote>\n<p><strong>Scaling Buffers:</strong>  During the <em>Scale-up Time</em>, the <em>Scaling Buffer</em> is the service's highest predicted traffic spike. Depending on the scaling strategy, we store several types of the buffer.</p>\n</blockquote>\n<p>Usually, we set a one million requests concurrency buffer. And based on the traffic pattern, our scaling automation triggers the scaling.</p>\n<h2 id=\"why-our-platform-performance-was-good-but-not-great\" style=\"position:relative;\"><a href=\"#why-our-platform-performance-was-good-but-not-great\" aria-label=\"why our platform performance was good but not great permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Our Platform Performance Was Good, But Not Great?</h2>\n<p>Our Platform performance is good. We can quickly handle millions of requests, and our application platform was scalable but not great. Minding the kind of growth we’re expecting, we wanted to improve and prepare our platform for the future.</p>\n<h3 id=\"challenges-in-the-existing-platform\" style=\"position:relative;\"><a href=\"#challenges-in-the-existing-platform\" aria-label=\"challenges in the existing platform permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Challenges in the Existing Platform</h3>\n<h4 id=\"1-startup-time\" style=\"position:relative;\"><a href=\"#1-startup-time\" aria-label=\"1 startup time permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Startup Time</h4>\n<p>No. of requests can fluctuate within a few seconds if not minutes or hours, especially with specific events such as holiday shopping, promotional events, Black Friday, etc. So, in the event of traffic spikes, application startup time plays a significant role in scaling.</p>\n<p>Our application startup time was around 90 seconds, so whenever scaling was happening due to high traffic, scaling took more time. That's why we needed to improve the application startup time.</p>\n<h4 id=\"2-cost\" style=\"position:relative;\"><a href=\"#2-cost\" aria-label=\"2 cost permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Cost</h4>\n<p>We used hundreds of <em>AWS c5.2xlarge</em> instances in a production environment to handle daily traffic. During certain events such as holiday shopping and Black Friday, we doubled our infrastructure according to expected traffic with a 20~30% buffer. We kept a high buffer because scaling took time with the existing .NET Core services. As a result, infrastructure cost was burdening as we were inefficiently deploying cloud infrastructure.</p>\n<h4 id=\"3-lack-of-flexibility-and-customization\" style=\"position:relative;\"><a href=\"#3-lack-of-flexibility-and-customization\" aria-label=\"3 lack of flexibility and customization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Lack of Flexibility and Customization</h4>\n<p>We designed our Identity Platform a few years ago. Since then, the technology landscape has dramatically improved and optimized in recent years. </p>\n<p>Also, current technology platforms available to build and support our product (Identity Platform) are limited. So, it is crucial to align functionality with proper technology capabilities.</p>\n<p>We were facing challenges in customization. It was inflexible and limiting to deliver the required outcomes in more complex situations and use cases.</p>\n<h2 id=\"the-road-to-lightning-performance-thanks-to-go\" style=\"position:relative;\"><a href=\"#the-road-to-lightning-performance-thanks-to-go\" aria-label=\"the road to lightning performance thanks to go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Road to Lightning Performance, Thanks to Go</h2>\n<h3 id=\"why-go\" style=\"position:relative;\"><a href=\"#why-go\" aria-label=\"why go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why <em>Go</em>?</h3>\n<p>We did a lot of research to choose the appropriate programming language for our application. We needed a language that would be simple to understand and learn, easy to maintain, and has high concurrency. Our research ended with Go due to its amazing qualities.</p>\n<p>Let's take a closer look. <em>Why choose Go? What makes Go such an excellent development language? What distinguishes it from the competition?</em> </p>\n<p>Let's get to the bottom of this by looking at what makes Go special.</p>\n<h3 id=\"go--background\" style=\"position:relative;\"><a href=\"#go--background\" aria-label=\"go  background permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Go — Background</h3>\n<p>Go is an open-source programming language developed by Google's Rob Pike, Robert Griesemer, and Ken Thompson. It was initially released in 2009. It has several enhancements and additions based on the C syntax to properly control memory use, manage objects, and enable static or strict typing along with concurrency.</p>\n<h4 id=\"1-concurrency\" style=\"position:relative;\"><a href=\"#1-concurrency\" aria-label=\"1 concurrency permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Concurrency</h4>\n<p>Concurrent code can be executed in parallel by separate computer cores or in sequence. Most programming languages lack concurrent execution when working with multiple threads. They often slow down programming, compiling, and execution.</p>\n<p>Go works with goroutines that are lightweight, low-cost threads. And Go channels allow goroutines to communicate with one another. </p>\n<p>Sequential Processes Communication: They are very similar to threads in Java but lightweight, and the cost of creating them is meager.</p>\n<h4 id=\"2-performance\" style=\"position:relative;\"><a href=\"#2-performance\" aria-label=\"2 performance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Performance</h4>\n<p>Go's core value is simplicity: it builds quickly, runs quickly, and is simple to learn. To help speed things up, there are no classes or type inheritance. This makes it easier to build a market-ready product quickly. Furthermore, its simplicity allows for quick and simple maintenance.</p>\n<h4 id=\"3-standard-library\" style=\"position:relative;\"><a href=\"#3-standard-library\" aria-label=\"3 standard library permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Standard Library</h4>\n<p>Go has an excellent standard library that includes a large number of built-in essential type functions and packages that are both practical and straightforward to use: I/O, encoding and decoding, manipulating raw bytes, network utility functions, parsing, debugging, and a lot more are all made simple by particular packages. Testing support is also included in the standard library, so no other dependencies are required.</p>\n<h4 id=\"4-easy-to-learn\" style=\"position:relative;\"><a href=\"#4-easy-to-learn\" aria-label=\"4 easy to learn permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4) Easy to Learn</h4>\n<p>Go has a simpler syntax than other languages and is simple to learn. The syntax of Go is somewhat similar to the C language. Developers can begin with Go in a couple of hours, but they need to spend time understanding best coding practices, especially understanding goroutines for concurrency.</p>\n<h2 id=\"benchmarking-api-performance-gains\" style=\"position:relative;\"><a href=\"#benchmarking-api-performance-gains\" aria-label=\"benchmarking api performance gains permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Benchmarking API Performance Gains</h2>\n<p>We run benchmarks on our API so that the performance insights help us make decisions about the tech stack. It will paint a clearer picture of where we stand compared to our existing tech stack and what areas need improvement or immediate attention. </p>\n<p>We did multiple stress tests on our high usage APIs built separately with .NET Core(Old) and Go (new). </p>\n<p>We are using Kubernetes to deploy and manage our microservices and application infrastructure and deploy our application microservices across multiple Pods.</p>\n<h3 id=\"stress-test-scenario\" style=\"position:relative;\"><a href=\"#stress-test-scenario\" aria-label=\"stress test scenario permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stress Test Scenario</h3>\n<table>\n<thead>\n<tr>\n<th>Test Item</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Instance Type</td>\n<td>c5.2xlarge on AWS</td>\n</tr>\n<tr>\n<td>No. of Instances</td>\n<td>20</td>\n</tr>\n<tr>\n<td>Reverse Proxy</td>\n<td>NGINX</td>\n</tr>\n<tr>\n<td>Concurrent Requests</td>\n<td>20K per second</td>\n</tr>\n<tr>\n<td>Duration</td>\n<td>5 minutes</td>\n</tr>\n<tr>\n<td>Stress Test Tool</td>\n<td><a href=\"https://gatling.io/\">Gatling</a></td>\n</tr>\n</tbody>\n</table>\n<p>We deployed both applications in the same infrastructure and did the same stress test.\nGolang application has performed much better.</p>\n<h4 id=\"existing-application-matrix--net-core\" style=\"position:relative;\"><a href=\"#existing-application-matrix--net-core\" aria-label=\"existing application matrix  net core permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Existing Application Matrix — .NET Core</h4>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 34.375%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABS0lEQVQY02VQXUvDMBTtn9+zCIK6Ca5sIFgQX4ZDfZqyl21siDp09mtZ27S1adeuH0ma1tupIHgIh3OTe88NRyp+QSlNkmS1Wum6rmkaCGDQqqr6vlcUeZalGVCeUVrAPcauxDkvy7LaQ4gSHigDHzAD0WjGSyHqv8jyapeyPM+lNE0ZZ1Vd7c9/gGO+Y2GQoq2+WETj5VxxZrOU1bBCiuO4Fj9TQtAM+gprnSyfyXjs3Qxt5QrJPfNYfjuYKq2jzeHgrvXy2GE1DDOJM66T17k/GtmDoaVco/6FcSYbnZ4J3G4EOu+j7qXefRid9Cz5dtK+n56a5KlkQoKFEQtRuHZi693eoAB7EXIDw4hMh9huiLGlYWLhCEPpxW6Q+JjYCY0hrCawCvIqm29jp8LOrojsgqCP0CCfwTbcZqpOXD8kEae8FjU0fzMk+gW3onx90KKwEAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Requests and Responses per Second (.NET Core)\" title=\"Requests and Responses per Second (.NET Core)\" src=\"/static/065af3c1452371eeef2cc2e9c6eecd81/01e7c/requests-and-responses-per-second-dot-net-core.png\" srcset=\"/static/065af3c1452371eeef2cc2e9c6eecd81/01e7c/requests-and-responses-per-second-dot-net-core.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 1(a): Requests and Responses per Second (.NET Core)</figcaption>\n</figure>\n \n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 33.7890625%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA6ElEQVQY042QzW7DIAzHef/n2GGXqn2FXSat0lRVmrRTliYpUZSlHoGEr2CoabepvdVY5sffNjKwrusAfuYb01qP41gUxeFQ1XVdliVx33+TPk25YNIzgTGG0WatXe7NOSeEkFIqJekiYuoMIVyz6ANioBpGOURMj1m8xNct9KNPCZlSCmN8uDmvp5e3ze6dgAFA8Dqhyx5sRBudyRBs+nXSXT6iQ7TJ+NXH+pmv0xLZ4v2iBwXHWbRqaCbgglfq1MzA5dBcFIq1puzpKPvKQvvJ91+ujQHZdR7M4yT8h3jn8Zb/nk7/dwaRrZNa00I0hQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"API Response Time (.NET Core)\" title=\"API Response Time (.NET Core)\" src=\"/static/10602d758e3df688d22b7e79cfa22e5f/01e7c/response-time-percentiles-dot-net-core.png\" srcset=\"/static/10602d758e3df688d22b7e79cfa22e5f/01e7c/response-time-percentiles-dot-net-core.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph -1(b): API Response Time (.NET Core)</figcaption>\n</figure>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 7.8125%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAYElEQVQI1zWIyw6AIAzA/P9f83nzKAoXM1FQBgxC4jCx6aFpU0qxxsABIYT0QYmujxhjzplP/CEi7z0AaH0iYjPv1Il7Ujgq7LeHnSSHq73eo3SDdP1quauiRidsyy7mBd6/bjpuZavGAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Overall Matrix (.NET Core)\" title=\"Overall Matrix (.NET Core)\" src=\"/static/bd266c07f16fd3b1904ef569a8ca6425/01e7c/overall-matrix-dot-net-core.png\" srcset=\"/static/bd266c07f16fd3b1904ef569a8ca6425/01e7c/overall-matrix-dot-net-core.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 1(c): Overall Matrix (.NET Core)</figcaption>\n</figure>\n<p>You can see some errors in Graph - 1(a) after ramping up to 15K users. Also, response time is increasing, as seen in Graph - 1(b).</p>\n<p>The application can recover after a couple of seconds, and after that, the application cannot respond. Application scaling is taking time. And existing infra cannot handle this spike, so the application crashes after 18K RPS.</p>\n<h4 id=\"new-application-matrix--go\" style=\"position:relative;\"><a href=\"#new-application-matrix--go\" aria-label=\"new application matrix  go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>New Application Matrix — Go</h4>\n<p>We did the same stress test with the new Go application. It is easily able to handle this kind of concurrency without any issue. </p>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 34.1796875%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABVElEQVQY012QS2vCQBSF8/8XRQtFkdQo1toKhS50UaQUWrAtXbrRqpOXMZPEPBwfmcyzk5RuerhcDnPPxx2uhv9UFMXxeFwsvk3TXAOwXK4AAJVfh1GY4/yUn/MyRljBLWCHYaQpjFIqlDjnjOECF0QFcGUIpepRSi5/JSjJCdqdNjFy1byCGRVSqJL/JDihhwz7LprP4ukrHI+9+wfHaIGLj3AimdQQOgheYYJhihIVPcxnyfQNjsbbu6FzbYB606w1Qa2hunmpW1cNs/4ePZUwJdSMZ1/h88R7HHmDoaN3rVbH1m9svWvrPafd93oDtztwO7eO0bfbqhtW8zN8KWG1EpHMy7zoGKy2vhsFUeJEsQVSy4+3MPEDd+XvNjCFQQZ3hyg5xcoUvLyUVl6LCcHKj0MofB/hPcSpt86cNElRhs7A2sdJlu5pQQWXZZhLzjgh5AfSS3h3N+xolgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Requests and Responses per Second (Go)\" title=\"Requests and Responses per Second (Go)\" src=\"/static/da6febfd92d89610654f4c6c921720cd/01e7c/requests-and-responses-per-second-go-lang.png\" srcset=\"/static/da6febfd92d89610654f4c6c921720cd/01e7c/requests-and-responses-per-second-go-lang.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 2(a): Requests and Responses per Second (Go)</figcaption>\n</figure>\n \n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 33.984375%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA70lEQVQY02VQy26DMBD0/39Jz/2A9lT1klNPLRIhisLDjgFjGxu8XqcLtCppRmNp1zsj7Q67lCXn3O8wTZPWOsuyPM+LosiP+VeWcSHmeXbO7ZWMXgghPQAAIgHASbPVjwJmjEHE24K08g4Ykb+XaP06T3vNYrbWYvrv+TNDOr7U/jz4Uv/6b3fmYLvoe7AtMbr+h16BlTDKw9Pb6fmjev0EI4MSoASJcR7pFEbb42Ss4qMSpm3ccKXCDdJrSe3YNz0/t6eLrhotKnOtXcd1VyfwFAMLECAixAS4cqsX0r3LDwVCkUTaE1PcSFOIFP43k/CT9PPUbq4AAAAASUVORK5CYII='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"API Response Time (Go)\" title=\"API Response Time (Go)\" src=\"/static/ac8ce361632cba137c0e2d02aef53c6a/01e7c/response-time-percentiles-go-lang.png\" srcset=\"/static/ac8ce361632cba137c0e2d02aef53c6a/01e7c/response-time-percentiles-go-lang.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph -2(b): API Response Time (Go)</figcaption>\n</figure>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 7.03125%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAIAAABR8BlyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAQklEQVQI1x3IQQ6AIAwAMP//RKPRgYJsDhyDKDeIt6aTfz4gZW1XIINiY7VczV1WnwD1TO/wjnkYKC8uzgdvQf6UDpLGNvVCnefiAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Overall Matrix (Go)\" title=\"Overall Matrix (Go)\" src=\"/static/397ef4b4903cbbacdb16a5ab45b0f16f/01e7c/overall-matrix-go-lang.png\" srcset=\"/static/397ef4b4903cbbacdb16a5ab45b0f16f/01e7c/overall-matrix-go-lang.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 2(c): Overall Matrix (Go)</figcaption>\n</figure>\n<p>The Go application can easily handle 20K ramp-up requests per second without any issue, as shown in Graph -2(a).</p>\n<p>You can see in Graph - 2(b) what the response time was after 2 min 47 sec for a couple of seconds. The Go application was scaling during that time. It is scaling quickly, so it is not impacting API request performance, and, also, the application can recover response API time as expected. </p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>In this article, you have learned how we have achieved better API performance by rebuilding them in Go, which were previously built in .NET Core. And you have understood our approach to this transition and how it increased the API performance of the LoginRadius Identity Platform.</p>\n<p>Leverage LoginRadius Identity Platform to build authentication functionality for your web and mobile apps. <a href=\"https://accounts.loginradius.com/auth.aspx?action=register\">Sign up for a free LoginRadius account here</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"June 06, 2022","updated_date":null,"title":"Why We Re-engineered LoginRadius APIs with Go?","tags":["Go","API",".NET","LoginRadius"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/b63787a6ecfda78c022020fe03233557/ee604/high-performance-identity-apis.png","srcSet":"/static/b63787a6ecfda78c022020fe03233557/69585/high-performance-identity-apis.png 200w,\n/static/b63787a6ecfda78c022020fe03233557/497c6/high-performance-identity-apis.png 400w,\n/static/b63787a6ecfda78c022020fe03233557/ee604/high-performance-identity-apis.png 800w,\n/static/b63787a6ecfda78c022020fe03233557/f3583/high-performance-identity-apis.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Vijay Singh Shekhawat","github":"code-vj","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/build-push-docker-images-golang/"},"html":"<p>Let's walk through how to build and push Docker images programmatically using Go. To do this, we need to talk to the Docker daemon via the <a href=\"https://docs.docker.com/engine/api/\">Docker Engine API</a>. This is similar to how the Docker CLI works, but instead of entering commands through a CLI, we'll be writing code with Docker's Go SDK.</p>\n<p>At the time of writing, the official Docker Go SDK <a href=\"https://docs.docker.com/engine/api/sdk/examples/\">docs</a> provide great examples of running basic Docker commands with Go. However, it's missing examples on building and pushing Docker images, so we'll go over those in this blog.</p>\n<p>Before we begin, this blog assumes you have a working knowledge of Docker and Go. We'll go over the following:</p>\n<ul>\n<li>Building an image from local source code</li>\n<li>Pushing an image to a remote registry</li>\n</ul>\n<h2 id=\"environment-setup\" style=\"position:relative;\"><a href=\"#environment-setup\" aria-label=\"environment setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Environment Setup</h2>\n<p>First, we need to set up the environment. Create a project and include the app we want to containerize:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mkdir docker-go-tutorial && cd docker-go-tutorial && mkdir node-hello</span></code></pre>\n<p>We'll add a simple Node.js app:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// node-hello/app.js</span>\n<span class=\"grvsc-line\">console.log(&quot;Hello From LoginRadius&quot;);</span></code></pre>\n<p>with the Dockerfile:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// node-hello/Dockerfile</span>\n<span class=\"grvsc-line\">FROM node:12</span>\n<span class=\"grvsc-line\">WORKDIR /src</span>\n<span class=\"grvsc-line\">COPY . .</span>\n<span class=\"grvsc-line\">CMD [ &quot;node&quot;, &quot;app.js&quot; ]</span></code></pre>\n<p>Next, install the <a href=\"https://docs.docker.com/engine/api/sdk/\">Go SDK</a>. These are the Docker related imports we will be using:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">&quot;github.com/docker/docker/api/types&quot;</span>\n<span class=\"grvsc-line\">&quot;github.com/docker/docker/client&quot;</span>\n<span class=\"grvsc-line\">&quot;github.com/docker/docker/pkg/archive&quot;</span></code></pre>\n<h2 id=\"build-docker-image\" style=\"position:relative;\"><a href=\"#build-docker-image\" aria-label=\"build docker image permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Build Docker Image</h2>\n<p>One way to build a Docker image from our local files is to compress those files into a tar archive first.</p>\n<p>We use the archive package provided by Docker:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">&quot;github.com/docker/docker/pkg/archive&quot;</span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">tar, err := archive.TarWithOptions(&quot;node-hello/&quot;, &archive.TarOptions{})</span>\n<span class=\"grvsc-line\">if err != nil {</span>\n<span class=\"grvsc-line\">    return err</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>Now, we can call the ImageBuild function using the Go SDK:</p>\n<ul>\n<li>\n<p>Note that the image tag includes our Docker registry user ID, so we can push this image to our registry later.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">opts := types.ImageBuildOptions{</span>\n<span class=\"grvsc-line\">Dockerfile:  &quot;Dockerfile&quot;,</span>\n<span class=\"grvsc-line\">Tags:        []string{dockerRegistryUserID + &quot;/node-hello&quot;},</span>\n<span class=\"grvsc-line\">Remove:      true,</span>\n<span class=\"grvsc-line\">}</span>\n<span class=\"grvsc-line\">res, err := dockerClient.ImageBuild(ctx, tar, opts)</span>\n<span class=\"grvsc-line\">if err != nil {</span>\n<span class=\"grvsc-line\">return err</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n</li>\n</ul>\n<p>To print the response, we use a scanner to go through line by line:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">scanner := bufio.NewScanner(res.Body)</span>\n<span class=\"grvsc-line\">for scanner.Scan() {</span>\n<span class=\"grvsc-line\">    lastLine = scanner.Text()</span>\n<span class=\"grvsc-line\">    fmt.Println(scanner.Text())</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>This prints the following:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 1/4 : FROM node:12&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e e4f1e16b3633\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 2/4 : WORKDIR /src&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e Using cache\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e b298b8519669\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 3/4 : COPY . .&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e Using cache\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e 1ff6a87e79d9\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 4/4 : CMD [ \\&quot;node\\&quot;, \\&quot;app.js\\&quot; ]&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e Using cache\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e 6ca44f72b68d\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;aux&quot;:{&quot;ID&quot;:&quot;sha256:238a923459uf28h80103eb089804a2ff2c1f68f8c&quot;}}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Successfully built 6ca44f72b68d\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Successfully tagged lrblake/node-hello:latest\\n&quot;}</span></code></pre>\n<p>The last step would be checking the response for errors, so if something went wrong during the build, we could handle it.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">errLine := &ErrorLine{}</span>\n<span class=\"grvsc-line\">json.Unmarshal([]byte(lastLine), errLine)</span>\n<span class=\"grvsc-line\">if errLine.Error != &quot;&quot; {</span>\n<span class=\"grvsc-line\">    return errors.New(errLine.Error)</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>For example, the following error can occur during build:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{&quot;errorDetail&quot;:{&quot;message&quot;:&quot;COPY failed: stat /var/lib/docker/tmp/docker-builder887191115/z: no such file or directory&quot;},&quot;error&quot;:&quot;COPY failed: stat /var/lib/docker/tmp/docker-builder887191115/z: no such file or directory&quot;}</span></code></pre>\n<p>All together, the file looks like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">package</span><span class=\"mtk1\"> main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;bufio&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;context&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;encoding/json&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;errors&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;io&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;time&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/docker/docker/api/types&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/docker/docker/client&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/docker/docker/pkg/archive&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">dockerRegistryUserID</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ErrorLine</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tError       </span><span class=\"mtk10\">string</span><span class=\"mtk1\">      </span><span class=\"mtk8\">`json:&quot;error&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tErrorDetail ErrorDetail </span><span class=\"mtk8\">`json:&quot;errorDetail&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ErrorDetail</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tMessage </span><span class=\"mtk10\">string</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`json:&quot;message&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">cli</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := client.</span><span class=\"mtk11\">NewClientWithOpts</span><span class=\"mtk1\">(client.FromEnv, client.</span><span class=\"mtk11\">WithAPIVersionNegotiation</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tfmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(err.</span><span class=\"mtk11\">Error</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">imageBuild</span><span class=\"mtk1\">(cli)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tfmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(err.</span><span class=\"mtk11\">Error</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">imageBuild</span><span class=\"mtk1\">(dockerClient *client.Client) </span><span class=\"mtk10\">error</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">cancel</span><span class=\"mtk1\"> := context.</span><span class=\"mtk11\">WithTimeout</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">Background</span><span class=\"mtk1\">(), time.Second*</span><span class=\"mtk7\">120</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">defer</span><span class=\"mtk1\"> </span><span class=\"mtk11\">cancel</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">tar</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := archive.</span><span class=\"mtk11\">TarWithOptions</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;node-hello/&quot;</span><span class=\"mtk1\">, &archive.TarOptions{})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">opts</span><span class=\"mtk1\"> := types.ImageBuildOptions{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tDockerfile: </span><span class=\"mtk8\">&quot;Dockerfile&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tTags:       []</span><span class=\"mtk10\">string</span><span class=\"mtk1\">{dockerRegistryUserID + </span><span class=\"mtk8\">&quot;/node-hello&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tRemove:     </span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">res</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := dockerClient.</span><span class=\"mtk11\">ImageBuild</span><span class=\"mtk1\">(ctx, tar, opts)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">defer</span><span class=\"mtk1\"> res.Body.</span><span class=\"mtk11\">Close</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(res.Body)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(rd io.Reader) </span><span class=\"mtk10\">error</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lastLine</span><span class=\"mtk1\"> </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">scanner</span><span class=\"mtk1\"> := bufio.</span><span class=\"mtk11\">NewScanner</span><span class=\"mtk1\">(rd)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">for</span><span class=\"mtk1\"> scanner.</span><span class=\"mtk11\">Scan</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">lastLine</span><span class=\"mtk1\"> = scanner.</span><span class=\"mtk11\">Text</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tfmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(scanner.</span><span class=\"mtk11\">Text</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">errLine</span><span class=\"mtk1\"> := &ErrorLine{}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tjson.</span><span class=\"mtk11\">Unmarshal</span><span class=\"mtk1\">([]</span><span class=\"mtk11\">byte</span><span class=\"mtk1\">(lastLine), errLine)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> errLine.Error != </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> errors.</span><span class=\"mtk11\">New</span><span class=\"mtk1\">(errLine.Error)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := scanner.</span><span class=\"mtk11\">Err</span><span class=\"mtk1\">(); err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The equivalent Docker CLI command would be:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">docker build -t &lt;dockerRegistryUserID&gt;/node-hello .</span></code></pre>\n<h2 id=\"push-docker-image\" style=\"position:relative;\"><a href=\"#push-docker-image\" aria-label=\"push docker image permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Push Docker Image</h2>\n<p>We'll push the Docker image we created to Docker Hub. But, we need to authenticate with Docker Hub by providing credentials encoded in base64.</p>\n<ul>\n<li>In practice, don't hardcode your credentials in your source code.</li>\n<li>\n<p>If you don't want to use your Docker Hub password, you can set up an access token and provide that in the Password field instead.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">var authConfig = types.AuthConfig{</span>\n<span class=\"grvsc-line\">Username:      &quot;Your Docker Hub Username&quot;,</span>\n<span class=\"grvsc-line\">Password:      &quot;Your Docker Hub Password or Access Token&quot;,</span>\n<span class=\"grvsc-line\">ServerAddress: &quot;https://index.docker.io/v1/&quot;,</span>\n<span class=\"grvsc-line\">}</span>\n<span class=\"grvsc-line\">authConfigBytes, _ := json.Marshal(authConfig)</span>\n<span class=\"grvsc-line\">authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)</span></code></pre>\n</li>\n</ul>\n<p>Now, call the ImagePush function in the Go SDK, along with your encoded credentials:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">opts := types.ImagePushOptions{RegistryAuth: authConfigEncoded}</span>\n<span class=\"grvsc-line\">rd, err := dockerClient.ImagePush(ctx, dockerRegistryUserID + &quot;/node-hello&quot;, opts)</span></code></pre>\n<p>Together, this looks like:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">func imagePush(dockerClient *client.Client) error {</span>\n<span class=\"grvsc-line\">\tctx, cancel := context.WithTimeout(context.Background(), time.Second*120)</span>\n<span class=\"grvsc-line\">\tdefer cancel()</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\tauthConfigBytes, _ := json.Marshal(authConfig)</span>\n<span class=\"grvsc-line\">\tauthConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\ttag := dockerRegistryUserID + &quot;/node-hello&quot;</span>\n<span class=\"grvsc-line\">\topts := types.ImagePushOptions{RegistryAuth: authConfigEncoded}</span>\n<span class=\"grvsc-line\">\trd, err := dockerClient.ImagePush(ctx, tag, opts)</span>\n<span class=\"grvsc-line\">\tif err != nil {</span>\n<span class=\"grvsc-line\">\t\treturn err</span>\n<span class=\"grvsc-line\">\t}</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\tdefer rd.Close()</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\terr = print(rd)</span>\n<span class=\"grvsc-line\">\tif err != nil {</span>\n<span class=\"grvsc-line\">\t\treturn err</span>\n<span class=\"grvsc-line\">\t}</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\treturn nil</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>The equivalent Docker CLI command (after docker login) would be:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">docker push &lt;dockerRegistryUserID&gt;/node-hello</span></code></pre>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"December 08, 2020","updated_date":null,"title":"Build and Push Docker Images with Go","tags":["Docker","Go"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.680672268907563,"src":"/static/f7f513d2d6c5460c9f71278fcb98f766/ee604/cover.png","srcSet":"/static/f7f513d2d6c5460c9f71278fcb98f766/69585/cover.png 200w,\n/static/f7f513d2d6c5460c9f71278fcb98f766/497c6/cover.png 400w,\n/static/f7f513d2d6c5460c9f71278fcb98f766/ee604/cover.png 800w,\n/static/f7f513d2d6c5460c9f71278fcb98f766/31987/cover.png 1000w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Andy Yeung","github":null,"avatar":null}}}},{"node":{"fields":{"slug":"/engineering/golang-maps/"},"html":"<p>Golang Maps is a compilation of unordered key-value pairs. It is commonly used because it offers simple searches and values with the aid of keys that can be retrieved, modified or deleted. It is a reference to a table with a hash.</p>\n<p>This blog will cover the basic use of maps in Go, and how a newcomer to the language may utilize them for their applications.</p>\n<h2 id=\"what-is-a-map\" style=\"position:relative;\"><a href=\"#what-is-a-map\" aria-label=\"what is a map permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is a Map?</h2>\n<p>Maps (also called dictionaries) are a very useful tool in helping to store and organize objects to be accessed in an efficient method. </p>\n<p>Most basic implementations of a map involve using a key to access a value in the map, resulting in key-value pairs, in which one key is associated with a specific value in the map. Within Golang, maps follow this definition.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 66.61538461538463%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUGAQP/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABX9m+SypSB//EABsQAAIDAAMAAAAAAAAAAAAAAAEDAAITBBEh/9oACAEBAAEFAlLLCeKzozPzG0yqJ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB8QAAEDAwUAAAAAAAAAAAAAAAABAhEQEiEiMTNxkf/aAAgBAQAGPwKGk4poWzo5XGyeH//EABsQAAICAwEAAAAAAAAAAAAAAAERACExQWFx/9oACAEBAAE/IS4LWXqNdPZQzRbyouEoVXghqEnUn//aAAwDAQACAAMAAAAQI8//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxBH/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERQf/aAAgBAgEBPxBTSn//xAAdEAEAAgICAwAAAAAAAAAAAAABABEhMUGhYYGR/9oACAEBAAE/EB6oWlQPLKixTjdr1AKICNMyasFjP0QgDBrf1GrDyrHqf//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Dictionary\"\n        title=\"Dictionary\"\n        src=\"/static/d9d54b7f1e01c89b7af93a3e87f2eec9/212bf/dictionary.jpg\"\n        srcset=\"/static/d9d54b7f1e01c89b7af93a3e87f2eec9/6aca1/dictionary.jpg 650w,\n/static/d9d54b7f1e01c89b7af93a3e87f2eec9/212bf/dictionary.jpg 768w,\n/static/d9d54b7f1e01c89b7af93a3e87f2eec9/670dc/dictionary.jpg 1650w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"how-to-create-a-map\" style=\"position:relative;\"><a href=\"#how-to-create-a-map\" aria-label=\"how to create a map permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to create a map?</h2>\n<p>Initialization of a map can be done using the <code>make</code> command. This is similar to the initialization of a slice:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">mapObject</span><span class=\"mtk1\"> := </span><span class=\"mtk11\">make</span><span class=\"mtk1\">(</span><span class=\"mtk4\">map</span><span class=\"mtk1\">[</span><span class=\"mtk10\">string</span><span class=\"mtk1\">]</span><span class=\"mtk10\">string</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>In this case, <code>mapObject</code> is a map that uses strings as a key to map to another string. When creating a map, the key type must be a type that is <code>Comparable</code>, or more specifically types that can be compared using the <code>==</code> operator.</p>\n<p>Examples of valid key types include booleans, numbers, strings and several other primitives can be used as keys. </p>\n<p>One more thing to note is that structs can be used as a key, provided that all the properties of the struct are <code>Comparable</code>.</p>\n<p>Maps can also be created using a map literal. For an empty map:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">mapObject</span><span class=\"mtk1\"> := </span><span class=\"mtk4\">map</span><span class=\"mtk1\">[</span><span class=\"mtk10\">string</span><span class=\"mtk1\">]</span><span class=\"mtk10\">string</span><span class=\"mtk1\">{}</span></span></code></pre>\n<p>Or for a map with initial data:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">mapObject</span><span class=\"mtk1\"> := </span><span class=\"mtk4\">map</span><span class=\"mtk1\">[</span><span class=\"mtk10\">string</span><span class=\"mtk1\">]</span><span class=\"mtk10\">string</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t“Key1”: “Value1”,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t“Key2”: “Value2”,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t“Key3”: “Value3”,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"how-to-use-go-maps-with-examples\" style=\"position:relative;\"><a href=\"#how-to-use-go-maps-with-examples\" aria-label=\"how to use go maps with examples permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to use Go Maps (with Examples)</h2>\n<h3 id=\"setting\" style=\"position:relative;\"><a href=\"#setting\" aria-label=\"setting permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting</h3>\n<p>Interaction with Go maps are similar to the dictionaries and maps of other languages. A simple way to return a value associated with the key is to use bracket notation. For example, to set a string value mapped to a string key:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">mapObject[“test”] = “test_value”</span></span></code></pre>\n<h3 id=\"fetching\" style=\"position:relative;\"><a href=\"#fetching\" aria-label=\"fetching permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Fetching</h3>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.30769230769231%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAgD/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAT/2gAMAwEAAhADEAAAAQGs4Km//8QAGBAAAwEBAAAAAAAAAAAAAAAAAAEREEH/2gAIAQEAAQUC5XREz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAQEBAAAAAAAAAAAAAAAAAAEAIP/aAAgBAQAGPwKTP//EABoQAQEAAgMAAAAAAAAAAAAAAAEAETEhcaH/2gAIAQEAAT8hHoxlhny4dkSQ7Jv/2gAMAwEAAgADAAAAECvP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/ENCf/8QAGxABAAICAwAAAAAAAAAAAAAAAQAhETFBUWH/2gAIAQEAAT8QJougqFIABOURMiPpNrEuwU7IAan/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Fetching\"\n        title=\"Fetching\"\n        src=\"/static/292ea3839b19a996d8a3c5aea66193b0/212bf/fetching.jpg\"\n        srcset=\"/static/292ea3839b19a996d8a3c5aea66193b0/6aca1/fetching.jpg 650w,\n/static/292ea3839b19a996d8a3c5aea66193b0/212bf/fetching.jpg 768w,\n/static/292ea3839b19a996d8a3c5aea66193b0/1cf64/fetching.jpg 1778w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Retrieving a value uses the same format.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">result</span><span class=\"mtk1\"> := mapObject[“test”]</span></span></code></pre>\n<p>The value of <code>result</code> will be the value assigned to <code>“test”</code> in the map. In the case where no key is found, the zero value of the type is returned instead. In this case, if there is no associated value with <code>“test”</code>, an empty string is returned.</p>\n<p>A boolean that returns the key’s existence can also be returned if two arguments are assigned from the retrieval. For example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">result</span><span class=\"mtk1\">, </span><span class=\"mtk12\">exists</span><span class=\"mtk1\"> := mapObject[“test”]</span></span></code></pre>\n<p>If <code>“test”</code> exists in the map, <code>result</code> will be the value associated with <code>“test”</code> and <code>exists</code> will be true. If <code>“test”</code> does not exist, <code>result</code> will be an empty string and <code>exists</code> will be false. This is useful when the map being used contains zero-values to distinguish between existence or whether the value is just zero.</p>\n<h3 id=\"deleting\" style=\"position:relative;\"><a href=\"#deleting\" aria-label=\"deleting permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deleting</h3>\n<p>Using Go’s built in delete method, key-value pairs can be deleted off the map. To delete the previous <code>“test”</code> key from the map, the following can be called:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">delete</span><span class=\"mtk1\">(mapObject, </span><span class=\"mtk8\">&quot;test&quot;</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>The delete method does not have a return value, so if the key does not exist in the map, nothing will happen.\nLength</p>\n<p>The number of key-value pairs of a map can be found using the len method:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">length</span><span class=\"mtk1\"> := </span><span class=\"mtk11\">len</span><span class=\"mtk1\">(mapObject)</span></span></code></pre>\n<h3 id=\"iterating\" style=\"position:relative;\"><a href=\"#iterating\" aria-label=\"iterating permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Iterating</h3>\n<p>Using Go’s range keyword, a map can be iterated through.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> </span><span class=\"mtk12\">key</span><span class=\"mtk1\">, </span><span class=\"mtk12\">value</span><span class=\"mtk1\"> := </span><span class=\"mtk15\">range</span><span class=\"mtk1\"> m {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Key:&quot;</span><span class=\"mtk1\">, key, </span><span class=\"mtk8\">&quot;Value:&quot;</span><span class=\"mtk1\">, value)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>There is no specific order in which the map is iterated. If a specific order is needed, a slice or other data structure can be used to store or hold data which can then be sorted and iterated through.</p>\n<h3 id=\"concurrency\" style=\"position:relative;\"><a href=\"#concurrency\" aria-label=\"concurrency permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Concurrency</h3>\n<p>Although Go has a lot of support for concurrency through the use of goroutines and channels, maps alone are not a reliable approach to handling data in a concurrent setting. </p>\n<p>To work with maps that support concurrency, a separate synchronization method should be used, like <code>sync.RWMutex</code>. Alternatively, an open source map package which implements the synchronizations can be used.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>With the market space and number of applications being created by Go increasing, hopefully this blog will help touch onto the basics of one of the major structures in Go.</p>\n<p>Although it doesn’t support concurrency, maps in Go are still a useful tool in most applications developed in Go, to reliably access and manage data.</p>\n<p>If you want to learn more about golang here is a quick guide on, <a href=\"/sending-emails-with-golang/\">how to send email with golang</a>. If you like what you read leave a comment or any question and will communicate further. </p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"September 25, 2020","updated_date":null,"title":"Golang Maps - A Beginner’s Guide","tags":["Go","dictionaries","maps"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/30bb9b9901e76f3498d68913a0675ea9/ee604/index.png","srcSet":"/static/30bb9b9901e76f3498d68913a0675ea9/69585/index.png 200w,\n/static/30bb9b9901e76f3498d68913a0675ea9/497c6/index.png 400w,\n/static/30bb9b9901e76f3498d68913a0675ea9/ee604/index.png 800w,\n/static/30bb9b9901e76f3498d68913a0675ea9/f3583/index.png 1200w,\n/static/30bb9b9901e76f3498d68913a0675ea9/0dadc/index.png 1500w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Chris Yee","github":null,"avatar":null}}}},{"node":{"fields":{"slug":"/engineering/mongodb-as-datasource-in-golang/"},"html":"<h2 id=\"before-you-get-started\" style=\"position:relative;\"><a href=\"#before-you-get-started\" aria-label=\"before you get started permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Before You Get Started</h2>\n<p>This tutorial assumes you have:</p>\n<ul>\n<li>A basic understanding of Go Language</li>\n<li>Latest GoLang version installed on your system</li>\n<li>Latest MongoDB version installed on your system</li>\n</ul>\n<p>In this tutorial, we will use the official <strong><a href=\"https://github.com/mongodb/mongo-go-driver/\">MongoDB Go Driver</a></strong> to manage our MongoDB database. In the due process, we will write a program to learn how to install the MongoDB Go Driver and perform CRUD operations with it.</p>\n<h2 id=\"installation\" style=\"position:relative;\"><a href=\"#installation\" aria-label=\"installation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Installation</h2>\n<p>First in an empty folder run the below command</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">go mod init gomongo</span></code></pre>\n<p><code>go mod init</code> creates a new go.mod file and automatically imports dependencies when you will run go program. Then create the file main.go and write the below code, We will explain what this code will do in a min.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">package</span><span class=\"mtk1\"> main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;context&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;log&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;go.mongodb.org/mongo-driver/bson&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;go.mongodb.org/mongo-driver/mongo&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;go.mongodb.org/mongo-driver/mongo/options&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Book - We will be using this Book type to perform crud operations</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Book</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  Title     </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  Author    </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ISBN      </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  Publisher </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  Copies     </span><span class=\"mtk10\">int</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Set client options</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">clientOptions</span><span class=\"mtk1\"> := options.</span><span class=\"mtk11\">Client</span><span class=\"mtk1\">().</span><span class=\"mtk11\">ApplyURI</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;mongodb://localhost:27017&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Connect to MongoDB</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">client</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := mongo.</span><span class=\"mtk11\">Connect</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), clientOptions)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Check the connection</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> = client.</span><span class=\"mtk11\">Ping</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Connected to MongoDB!&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">booksCollection</span><span class=\"mtk1\"> := client.</span><span class=\"mtk11\">Database</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;testdb&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">Collection</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;books&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>In the above code, we have imported the bson, mongo, and mongo/options packages of mongo-driver and defined a <code>Book</code> type which will be used in this tutorial</p>\n<p>In the main function first, we created clientOptions with MongoDB URL and credentials and pass it to <code>mongo.Connect</code> function, Once connected we can check our connection by <code>client.Ping</code> function.</p>\n<p>The following code will use <code>booksCollection</code> variable to query the <code>books</code> collection from testdb.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">booksCollection</span><span class=\"mtk1\"> := client.</span><span class=\"mtk11\">Database</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;testdb&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">Collection</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;books&quot;</span><span class=\"mtk1\">)</span></span></code></pre>\n<h2 id=\"insert-documents\" style=\"position:relative;\"><a href=\"#insert-documents\" aria-label=\"insert documents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Insert Documents</h2>\n<p>First Let's create a Book struct to insert into the collection, in below code we are using <code>collection.InsertOne</code> function to insert a single document in the collection</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// Insert One document</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">book1</span><span class=\"mtk1\"> := Book{</span><span class=\"mtk8\">&quot;Animal Farm&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;George Orwell&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;0451526341&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Signet Classics&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">100</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">insertResult</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := booksCollection.</span><span class=\"mtk11\">InsertOne</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), book1)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Inserted a single document: &quot;</span><span class=\"mtk1\">, insertResult.InsertedID)</span></span></code></pre>\n<p>To insert multiple documents at once we need to create a slice of <code>Book</code> object and pass it to <code>collection.InsertMany</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// Insert multiple documents</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">book2</span><span class=\"mtk1\"> := Book{</span><span class=\"mtk8\">&quot;Super Freakonomics&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Steven D. Levitt&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;0062312871&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;HARPER COLLINS USA&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">100</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">book3</span><span class=\"mtk1\"> := Book{</span><span class=\"mtk8\">&quot;The Alchemist&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Paulo Coelho&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;0062315005&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;HarperOne&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">100</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">multipleBooks</span><span class=\"mtk1\"> := []</span><span class=\"mtk4\">interface</span><span class=\"mtk1\">{}{book2, book3}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">insertManyResult</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := booksCollection.</span><span class=\"mtk11\">InsertMany</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), multipleBooks)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Inserted multiple documents: &quot;</span><span class=\"mtk1\">, insertManyResult.InsertedIDs)</span></span></code></pre>\n<h2 id=\"update-documents\" style=\"position:relative;\"><a href=\"#update-documents\" aria-label=\"update documents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Update Documents</h2>\n<p>We can update a single document by function  <code>collection.UpdateOne</code>. It requires a filter document to match documents in the collection and an updated document to describe the update operation. You can build these using bson.D types. The below code will match the book with <em>ISBN</em> <em>0451526341</em> and increment the copies field by <em>10</em></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">//Update one document</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">filter</span><span class=\"mtk1\"> := bson.D{{</span><span class=\"mtk8\">&quot;isbn&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;0451526341&quot;</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">update</span><span class=\"mtk1\"> := bson.D{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk8\">&quot;$inc&quot;</span><span class=\"mtk1\">, bson.D{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        {</span><span class=\"mtk8\">&quot;copies&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">10</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">updateResult</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := booksCollection.</span><span class=\"mtk11\">UpdateOne</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), filter, update)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">fmt.</span><span class=\"mtk11\">Printf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Matched %v documents and updated %v documents.</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, updateResult.MatchedCount, updateResult.ModifiedCount)</span></span></code></pre>\n<blockquote>\n<p>You can also update more than one documents at once in a single collection by function <code>collection.UpdateMany</code>, In it, we need to pass filter document and update document same as <code>collection.UpdateOne</code></p>\n</blockquote>\n<h2 id=\"find-documents\" style=\"position:relative;\"><a href=\"#find-documents\" aria-label=\"find documents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Find Documents</h2>\n<p>To find a single document, we can use function <code>collection.FindOne()</code>, we will pass a filter document and decode the result in the <code>Book</code> type variable</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// A variable in which result will be decoded</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">result</span><span class=\"mtk1\"> Book</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">err</span><span class=\"mtk1\"> = booksCollection.</span><span class=\"mtk11\">FindOne</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), filter).</span><span class=\"mtk11\">Decode</span><span class=\"mtk1\">(&result)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">fmt.</span><span class=\"mtk11\">Printf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Found a single document: %+v</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, result)</span></span></code></pre>\n<p>To find multiple documents, we use function <code>collection.Find()</code>. This method returns a Cursor, It provides a stream of documents on which we can iterate or we can get all the docs by function <code>cursor.All()</code> in a slice of <code>Book</code> type. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">cursor</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := booksCollection.</span><span class=\"mtk11\">Find</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), bson.D{{}})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">books</span><span class=\"mtk1\"> []Book</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> = cursor.</span><span class=\"mtk11\">All</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), &books); err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">fmt.</span><span class=\"mtk11\">Printf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Found multiple documents: %+v</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, books)</span></span></code></pre>\n<h2 id=\"delete-documents\" style=\"position:relative;\"><a href=\"#delete-documents\" aria-label=\"delete documents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Delete Documents</h2>\n<p>We can delete documents from a collection using functions <code>collection.DeleteOne()</code> or <code>collection.DeleteMany()</code>. Here you pass bson.D{{}} as the filter argument, which will match all documents in the collection.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">deleteCollection</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := booksCollection.</span><span class=\"mtk11\">DeleteMany</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">(), bson.D{{}})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">fmt.</span><span class=\"mtk11\">Printf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Deleted %v documents in the books collection</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, deleteCollection.DeletedCount)</span></span></code></pre>\n<blockquote>\n<p>Entire collection can be dropped using the collection.Drop() function, it will remove all documents and metadata, such as indexes from the collection</p>\n</blockquote>\n<p>Once you have done all the operation, don't forget to close the MongoDB connection</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">err</span><span class=\"mtk1\"> = client.</span><span class=\"mtk11\">Disconnect</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">TODO</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Connection to MongoDB closed.&quot;</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>Now you can easily use MongoDB as Datasource in your go application, You can found the complete code used in this tutorial on our <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/GoLang/MongoDriverForGolang\">Github Repo</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n</style>","frontmatter":{"date":"September 21, 2020","updated_date":null,"title":"Using MongoDB as Datasource in GoLang","tags":["Go","MongoDB"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/462778a1e1bc2468232a76699885ec69/ee604/gomongo.png","srcSet":"/static/462778a1e1bc2468232a76699885ec69/69585/gomongo.png 200w,\n/static/462778a1e1bc2468232a76699885ec69/497c6/gomongo.png 400w,\n/static/462778a1e1bc2468232a76699885ec69/ee604/gomongo.png 800w,\n/static/462778a1e1bc2468232a76699885ec69/f3583/gomongo.png 1200w,\n/static/462778a1e1bc2468232a76699885ec69/5707d/gomongo.png 1600w,\n/static/462778a1e1bc2468232a76699885ec69/eeb1b/gomongo.png 1920w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Puneet Singh","github":"puneetsingh24","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/what-is-the-new-go-1-15/"},"html":"<p>Go announced <a href=\"https://blog.golang.org/\">Go 1.15</a> version on 11 Aug 2020. Highlighted updates and features include Substantial improvements to the Go linker, Improved allocation for small objects at high core counts, X.509 CommonName deprecation, GOPROXY supports skipping proxies that return errors, New embedded tzdata package, Several Core Library improvements and more. </p>\n<p>As <a href=\"https://golang.org/doc/go1compat\">Go promise</a> for maintaining backward compatibility. After upgrading to the latest Go 1.15 version, almost all existing Golang applications or programs continue to compile and run as older Golang version.</p>\n<p>Download the latest Go Version from <a href=\"https://golang.org/dl/\">Golang</a>.</p>\n<h3 id=\"operating-system-and-platform-compatibility\" style=\"position:relative;\"><a href=\"#operating-system-and-platform-compatibility\" aria-label=\"operating system and platform compatibility permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Operating system and platform compatibility</h3>\n<h4 id=\"macos\" style=\"position:relative;\"><a href=\"#macos\" aria-label=\"macos permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>macOS</h4>\n<p>Go 1.14 version announced some changes for the macOS. According to announcement  </p>\n<blockquote>\n<p>Go 1.14 is the last release that will run on macOS 10.11 El Capitan. Go 1.15 will require macOS 10.12 Sierra or later.</p>\n</blockquote>\n<p>The lastest macOS 10.15 (Catalina) is no longer supporting 32-bit binaries. Go 1.14 will likely to be the last Go release to support 32-bit binaries on iOS, iPadOS, watchOS, and tvOS (the darwin/arm port). Go continues to support the 64-bit darwin/amd64 port.</p>\n<h4 id=\"windows\" style=\"position:relative;\"><a href=\"#windows\" aria-label=\"windows permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Windows</h4>\n<p>Go now generates Windows ASLR executables when -buildmode=pie cmd/link flag is provided. Go command uses <code>-buildmode=pie</code> by default on Windows.</p>\n<p>The -race and -msan flags now always enable <code>-d=checkptr</code>, which checks uses of unsafe. Pointer. This was previously the case on all OSes except Windows.</p>\n<h4 id=\"android\" style=\"position:relative;\"><a href=\"#android\" aria-label=\"android permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Android</h4>\n<p>Mobile applications were crashing in some devices due to some invalid lld linker versions so now avoiding the crashing the latest Go 1.15 version explicitly selects the lld linker available in recent versions of the NDK. This explicitly lld linker avoids crashes on some devices. it becomes the default NDK linker in a future NDK version.</p>\n<h3 id=\"smaller-binaries--performance-improvements\" style=\"position:relative;\"><a href=\"#smaller-binaries--performance-improvements\" aria-label=\"smaller binaries  performance improvements permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Smaller binaries &#x26; Performance improvements</h3>\n<p>Always new Go 1.15 brings many minor/major performance improvements. The first major improvement has reduced the executable's binary size by almost 5% - 10% as compared to Go 1.14. As Brad Fitzpatrick <a href=\"https://twitter.com/bradfitz/status/1256348714198654976?lang=en\">tweet</a>, test program down from 8.2MB in Go 1.14 to 3.9MB in 1.15. </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 80.76923076923077%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAACiUlEQVQ4y5WTW2/aQBCFnXD3FdvccTAYgzH1BeMQIJCkuTV5iCpVykulqv//X5zOLEJVW6VpH45md737zczxrrTcP+L5y1e8vH7D5u4Fo3gLL9liEK5ovEFz+AHW2Qz2IETDnYv5MR51nLe9GFK6uUW2e8D+8TO29y9YXD4gv3pCsrnDcv8Jq5tnZLQWrz+iNYr+gP2eQHLnFxhFG0Sra4TLPcL8CvPza8wppts7Me5NUpH9ePhvkuLzNTZX1wjyG/iLHTxq04vW8KntINtR67kA2XzgWNFbYuDTfY7vr2tY0Q3s+Ba2l8I+C4Rn7J3p8HhGIGrLfUfcsmL1IJ2WUFNUdPtnGI0ncEdjJIulkOdPoOp1FEoVFMvVN1UolaE3HUiybkGSJBSLRTj9PrLFAlEUwXUH6HY6UBUF5VJJ7HlPSr1JQKMhJgUCdrpdxHGM3W6Hi4s1ujT/F5AknRyAZvsnsERVNJtNjMdjpGkK3/dxcnLYeIzvVmi2IFW1Q8unpwUBzLIM0+lUVMrzarX6HxUSsD+coFatQNcNWJaFDvnGMk0TffK01+vRNx0Kecmq1+tQVfXtCmfxEsOhiyAIEIahiI7joNFoCHES9pJBrVZLJONEnMQwDMiyDE3TSCpUizz0ggiddpugQ+EfH+aqGM5gBnBkiOu6AswQFlfKVXNSs24cgH6YwB0MRPYugZIkERrQGkNqtZrwkce2bRNAPVRHYAbphv5ry64/o7uXUBV99AnIVyagn7JcZri83Ir7mOc5XaMVPG8k9qRpgl5KXV07cNYd6MODp7JB99CdRvRC6IM7Qk0l8zXyheJBhljTDFOs1xQNFVkVsazJKOsyKoaCCvnHr4Vfyg/oqpwpFWDL7wAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"image 1\"\n        title=\"image 1\"\n        src=\"/static/216a02ed439988a46672b5b77a351a6a/e5715/lr-tweet1.png\"\n        srcset=\"/static/216a02ed439988a46672b5b77a351a6a/a6d36/lr-tweet1.png 650w,\n/static/216a02ed439988a46672b5b77a351a6a/e5715/lr-tweet1.png 768w,\n/static/216a02ed439988a46672b5b77a351a6a/dd104/lr-tweet1.png 1064w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 80.76923076923077%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAACYUlEQVQ4y5WSW3eaUBCFQV0rUcGIIqgEEbkoF0G8BWM0Mdqmq13NS/vWvvX//4bdYUy72jfz8K05Z2D22XPOCNvTK758/4lvP35hc3xFuD4gWD7Cm20xWexxO56j781g+LO3mOGWKPbFuuemnNdHU2h2DCHJn7Hcv2C1/4Tp3QGL3Qtm90fihPn2A4LFDvHqEUl+QLx+4n9mmyMiyqWbZ+LIdJ0EqhVCcJMcXrpBuNxzQfFjQbEeZ1sWYpH7s0hxQCHEhz98pLodCxV0hiTopfd8wpScTuYP/wkGdMgovsMwWsGO1hSJcAWLKHLONIc5WZBQTESM4JO7NH9iMnKxOXzGw+krtbnHlNCsAM2+A8XwoPTdc2Rcyp/3bdMnxueWr+UWBEFAS+1gmqRIZxk0vYtypUJ5EaVy5SLEUgk32gBCVbphQUVRMB6PEQQB2u0WyuUy59+DrPYhyIrKG1Es4erqCtVqFbIss7v3CjZUA4LWM6GqbViWhU6ng1qtxsL1ep1dt1otzl3mkASv31ru9XrcbpIk8H0fruvyFYRhCMdxIEnS+wR1XedCz/OYQkxVVXZZfC/RpV8kWJWavDHNAaIoYodpmmK32yHPc76Kyx/lH4dFYZZlWC6XLLTdbrFer/+2KoriZYI1+dySQpdvGAZj2zY/0HA4JOcmjZF6+SsbgxEaUh2NhowajYyuddCl+1RpFq/ptc/uBFRoLsViTZRLNPCUK4l/4pvDNs2hMZrAGnlQu7fQDQvJfAU/TOBOYoyjBNJNm/GCGH3ThtY3YTk+BlRjewFH03ZRk5to9mz8BmAjmKWlNCj4AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"image 1\"\n        title=\"image 1\"\n        src=\"/static/f97cca2c10ac4080b1558296d5a61401/e5715/lr-tweet2.png\"\n        srcset=\"/static/f97cca2c10ac4080b1558296d5a61401/a6d36/lr-tweet2.png 650w,\n/static/f97cca2c10ac4080b1558296d5a61401/e5715/lr-tweet2.png 768w,\n/static/f97cca2c10ac4080b1558296d5a61401/dd104/lr-tweet2.png 1064w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Go 1.15 has improved the code build process now unused code is eliminating in the new linker, along with several targeted improvements, such as Clements's CL 230544, which reduces the number of stack and register maps included in the executable.  </p>\n<h3 id=\"standard-library-additions\" style=\"position:relative;\"><a href=\"#standard-library-additions\" aria-label=\"standard library additions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Standard library additions</h3>\n<p>Always in every new version release Go come with various minor changes and updates to the library. I m including some useful and important changes  </p>\n<h4 id=\"tzdata-package\" style=\"position:relative;\"><a href=\"#tzdata-package\" aria-label=\"tzdata package permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>tzdata Package</h4>\n<p>A new embedded tzdata package was added that permits embedding the timezone database into a program. Importing this package (as import _ \"time/tzdata\") which allows the program to find timezone information without the timezone database on the local system. We can also embed the timezone database by building with -tags timet/zdata. This approach increases the size of the program by about 800 KB. This might be useful and can test some code with the virtualized environments like <a href=\"https://play.golang.org/\">Go playground</a>.</p>\n<h4 id=\"x509-commonname-deprecation\" style=\"position:relative;\"><a href=\"#x509-commonname-deprecation\" aria-label=\"x509 commonname deprecation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>X.509 CommonName deprecation</h4>\n<p>Go older versions were using CommonName field on X.509 certificates as a hostname if there is no Subject\nAlternative Names, would be disabled by default. If Still want to use this legacy behavior then we need to add x509ignoreCN=0 in the GODEBUG environment variable.</p>\n<h4 id=\"neturl-package\" style=\"position:relative;\"><a href=\"#neturl-package\" aria-label=\"neturl package permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>net/url Package</h4>\n<p>The <code>net/url</code> package adds a new URL. The redacted () method that returns the URL as a string. This is proposed in the <a href=\"https://github.com/golang/go/issues/34855\">Issue 34855</a>. It is a very useful improvement for audit logging and security. It's a simple derivation from the URL.String() that masks the password if exists from the string being passed. It does not modify at all to the URL itself but a copy of it.</p>\n<h3 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h3>\n<p>Go 1.15 has released with various improvements, bug fixes. We can get all improvements, closed proposals and features details for the Go GitHub repository.</p>\n<h3 id=\"referance\" style=\"position:relative;\"><a href=\"#referance\" aria-label=\"referance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Referance</h3>\n<ul>\n<li><a href=\"https://blog.golang.org/\">Go Blog</a></li>\n<li><a href=\"https://golang.org/doc/go1.15\">Go 1.15</a></li>\n</ul>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"September 07, 2020","updated_date":null,"title":"What's new in the go 1.15","tags":["Go","Golang","Go 1.15"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7699115044247788,"src":"/static/d85b112d59a5149f84548b866984f6db/ee604/index.png","srcSet":"/static/d85b112d59a5149f84548b866984f6db/69585/index.png 200w,\n/static/d85b112d59a5149f84548b866984f6db/497c6/index.png 400w,\n/static/d85b112d59a5149f84548b866984f6db/ee604/index.png 800w,\n/static/d85b112d59a5149f84548b866984f6db/f3583/index.png 1200w,\n/static/d85b112d59a5149f84548b866984f6db/5707d/index.png 1600w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Vijay Singh Shekhawat","github":"code-vj","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/sending-emails-with-golang/"},"html":"<h2 id=\"before-you-get-started\" style=\"position:relative;\"><a href=\"#before-you-get-started\" aria-label=\"before you get started permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Before You Get Started</h2>\n<p>This tutorial assumes you have:</p>\n<ul>\n<li>A basic understanding of Go Language</li>\n<li>Latest GoLang version installed on your system</li>\n<li>A few minutes of your time.</li>\n</ul>\n<p>In this blog, we’ll look at different methods to send an email with Go, First, we will explore inbuilt <strong><a href=\"https://golang.org/pkg/net/smtp/\">smtp package</a></strong>, then we will move to use a popular package <strong><a href=\"https://github.com/go-gomail/gomail\">Gomail</a></strong> and finally, we will send <strong>HTML emails</strong> using custom templates.</p>\n<h2 id=\"package-smtp\" style=\"position:relative;\"><a href=\"#package-smtp\" aria-label=\"package smtp permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Package smtp</h2>\n<p><strong>smtp</strong> is an inbuilt package provided with Golang. It implements the Simple Mail Transfer Protocol and has multiple functionalities related to it. Here to send the email we will be using only two functions <strong>PlainAuth</strong> and <em>SendMail</em> from the package.</p>\n<blockquote>\n<p>Note: <a href=\"https://compile7.org/decompile/go-functions-with-examples/\">Click here for an overview on Go Functions</a></p>\n</blockquote>\n<ul>\n<li><strong>PlainAuth</strong>: It uses the given username and password to authenticate to host and return an identity</li>\n<li><strong>SendMail</strong>: It connects to the server at address, switches to TLS if possible, authenticates with the optional mechanism an if possible, and then sends an email to the sender.</li>\n</ul>\n<p>Below is the complete code to send a plain text email with smtp package in golang.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">package</span><span class=\"mtk1\"> main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;net/smtp&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Sender data.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">from</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;from@gmail.com&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">password</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;&lt;Email Password&gt;&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Receiver email address.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">to</span><span class=\"mtk1\"> := []</span><span class=\"mtk10\">string</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;sender@example.com&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// smtp server configuration.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">smtpHost</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;smtp.gmail.com&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">smtpPort</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;587&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Message.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">message</span><span class=\"mtk1\"> := []</span><span class=\"mtk11\">byte</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;This is a test email message.&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Authentication.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">auth</span><span class=\"mtk1\"> := smtp.</span><span class=\"mtk11\">PlainAuth</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, from, password, smtpHost)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Sending email.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := smtp.</span><span class=\"mtk11\">SendMail</span><span class=\"mtk1\">(smtpHost+</span><span class=\"mtk8\">&quot;:&quot;</span><span class=\"mtk1\">+smtpPort, auth, from, to, message)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Email Sent Successfully!&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<blockquote>\n<p>In the above code example we have used smtp details of a Gmail account, you should update the smtp detail according to your email provider.</p>\n</blockquote>\n<blockquote>\n<p>Just to explain things easily, In the above snippet, we have written all the smtp and email credentials in the main function, Though in a production app you should always use env variables for configurations. You can check <a href=\"https://github.com/spf13/viper\">Viper</a> to manage configurations in production apps.</p>\n</blockquote>\n<h2 id=\"package-gomail\" style=\"position:relative;\"><a href=\"#package-gomail\" aria-label=\"package gomail permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Package Gomail</h2>\n<p>Below is the complete code to send a plain text email with Gomail package in golang.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">package</span><span class=\"mtk1\"> main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;crypto/tls&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  gomail </span><span class=\"mtk8\">&quot;gopkg.in/mail.v2&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">m</span><span class=\"mtk1\"> := gomail.</span><span class=\"mtk11\">NewMessage</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Set E-Mail sender</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  m.</span><span class=\"mtk11\">SetHeader</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;From&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;from@gmail.com&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Set E-Mail receivers</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  m.</span><span class=\"mtk11\">SetHeader</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;To&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;to@example.com&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Set E-Mail subject</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  m.</span><span class=\"mtk11\">SetHeader</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Subject&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Gomail test subject&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Set E-Mail body. You can set plain text or html with text/html</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  m.</span><span class=\"mtk11\">SetBody</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;text/plain&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;This is Gomail test body&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Settings for SMTP server</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">d</span><span class=\"mtk1\"> := gomail.</span><span class=\"mtk11\">NewDialer</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;smtp.gmail.com&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">587</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;from@gmail.com&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;&lt;email_password&gt;&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// This is only needed when SSL/TLS certificate is not valid on server.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// In production this should be set to false.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">d.TLSConfig</span><span class=\"mtk1\"> = &tls.Config{InsecureSkipVerify: </span><span class=\"mtk4\">true</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Now send E-Mail</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := d.</span><span class=\"mtk11\">DialAndSend</span><span class=\"mtk1\">(m); err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">panic</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"custom-html-templates\" style=\"position:relative;\"><a href=\"#custom-html-templates\" aria-label=\"custom html templates permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Custom HTML Templates</h2>\n<p>Now, let's send an HTML email with smtp package, for this, we need to create two files in the root folder.</p>\n<ul>\n<li>main.go: go code to parse HTML template and send it in email</li>\n<li>template.html : HTML template for emails</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- </span><span class=\"mtk12\">template</span><span class=\"mtk1\">.</span><span class=\"mtk12\">html</span><span class=\"mtk1\"> --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h3</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Name:</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h3</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">Name</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">br</span><span class=\"mtk17\">/&gt;&lt;</span><span class=\"mtk4\">br</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h3</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Email:</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h3</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">Message</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">br</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>We are using <a href=\"https://golang.org/pkg/text/template/\">text/template</a> package to parse HTML files and use it in smtp SendMail function.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">package</span><span class=\"mtk1\"> main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;bytes&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;net/smtp&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;text/template&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Sender data.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">from</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;from@gmail.com&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">password</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;&lt;Email Password&gt;&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Receiver email address.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">to</span><span class=\"mtk1\"> := []</span><span class=\"mtk10\">string</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;sender@example.com&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// smtp server configuration.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">smtpHost</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;smtp.gmail.com&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">smtpPort</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;587&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Authentication.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">auth</span><span class=\"mtk1\"> := smtp.</span><span class=\"mtk11\">PlainAuth</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">, from, password, smtpHost)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">t</span><span class=\"mtk1\">, </span><span class=\"mtk12\">_</span><span class=\"mtk1\"> := template.</span><span class=\"mtk11\">ParseFiles</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;template.html&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">body</span><span class=\"mtk1\"> bytes.Buffer</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">mimeHeaders</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;MIME-version: 1.0;</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">Content-Type: text/html; charset=</span><span class=\"mtk6\">\\&quot;</span><span class=\"mtk8\">UTF-8</span><span class=\"mtk6\">\\&quot;</span><span class=\"mtk8\">;</span><span class=\"mtk6\">\\n\\n</span><span class=\"mtk8\">&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  body.</span><span class=\"mtk11\">Write</span><span class=\"mtk1\">([]</span><span class=\"mtk11\">byte</span><span class=\"mtk1\">(fmt.</span><span class=\"mtk11\">Sprintf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Subject: This is a test subject </span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">%s</span><span class=\"mtk6\">\\n\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, mimeHeaders)))</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  t.</span><span class=\"mtk11\">Execute</span><span class=\"mtk1\">(&body, </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    Name    </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    Message </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    Name:    </span><span class=\"mtk8\">&quot;Puneet Singh&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    Message: </span><span class=\"mtk8\">&quot;This is a test message in a HTML template&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Sending email.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := smtp.</span><span class=\"mtk11\">SendMail</span><span class=\"mtk1\">(smtpHost+</span><span class=\"mtk8\">&quot;:&quot;</span><span class=\"mtk1\">+smtpPort, auth, from, to, body.</span><span class=\"mtk11\">Bytes</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  fmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Email Sent!&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Once done you need to run below command to send the emails</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">go run main.go</span></code></pre>\n<blockquote>\n<p>If you don't want to create your custom HTML emails, <a href=\"https://github.com/matcornic/hermes\">Hermes</a> is a package that generates clean, responsive HTML e-mails for sending transactional e-mails.</p>\n</blockquote>\n<p>Now you can send beautiful emails to the customer by your golang application, You can found the complete code used in this blog on our <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/GoLang/DifferentWaysToSendEmail\">Github Repo</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n</style>","frontmatter":{"date":"August 03, 2020","updated_date":null,"title":"Different ways to send an email with Golang","tags":["Go","Email"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/0ac40484af2392675963fb3327b3dbb4/14b42/email_cover.jpg","srcSet":"/static/0ac40484af2392675963fb3327b3dbb4/f836f/email_cover.jpg 200w,\n/static/0ac40484af2392675963fb3327b3dbb4/2244e/email_cover.jpg 400w,\n/static/0ac40484af2392675963fb3327b3dbb4/14b42/email_cover.jpg 800w,\n/static/0ac40484af2392675963fb3327b3dbb4/47498/email_cover.jpg 1200w,\n/static/0ac40484af2392675963fb3327b3dbb4/0e329/email_cover.jpg 1600w,\n/static/0ac40484af2392675963fb3327b3dbb4/52258/email_cover.jpg 1800w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Puneet Singh","github":"puneetsingh24","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/twitter-authentication-with-golang-and-goth/"},"html":"<p>In this blog, we’ll be implementing authentication via Twitter in a Golang web application. For this, we’ll be using Goth, a social authentication middleware for Golang.</p>\n<p>Pre-requisites: </p>\n<ul>\n<li>Basic knowledge of HTML/Golang</li>\n<li>Golang should be installed in your system</li>\n</ul>\n<p><strong>Firstly</strong>, We need to create a new Twitter App using its <a href=\"https://apps.twitter.com/\">Application Management</a>. Twitter does not seem to work nicely with it if \"localhost\" is given in the callback URL field. To overcome this limitation, you could use the special loopback address or <strong>\"127.0.0.1\"</strong> in place of <strong>\"localhost\"</strong>.</p>\n<p>Step 1. First, create a directory structure as below for your Go Application :</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">TwitterAuthenticationGoth</span>\n<span class=\"grvsc-line\">-templates</span>\n<span class=\"grvsc-line\">--index.html</span>\n<span class=\"grvsc-line\">--success.html</span>\n<span class=\"grvsc-line\">-main.go</span></code></pre>\n<p>Step 2. Add the following code in <strong>index.html</strong> for creating <strong>LoginUI</strong>:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">doctype</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Twitter SignIn</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load bulma css --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load fontawesome --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        body        </span><span class=\"mtk4\">{</span><span class=\"mtk1\"> </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">-</span><span class=\"mtk12\">top</span><span class=\"mtk1\">:70</span><span class=\"mtk12\">px</span><span class=\"mtk1\">; </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;jumbotron text-center text-success&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fa fa-lock&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Social Authentication</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Login or Register with:</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/auth/twitter&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;btn btn-danger&quot;</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fa fa-twitter&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> SignIn with Twitter</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">a</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> </span></span></code></pre>\n<p>Step 3 Add the following code in <strong>success.html</strong> for creating <strong>ProfileUI</strong>:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">doctype</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Twitter SignIn</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load bulma css --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load fontawesome --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          body        </span><span class=\"mtk4\">{</span><span class=\"mtk1\"> </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">-</span><span class=\"mtk12\">top</span><span class=\"mtk1\">:70</span><span class=\"mtk12\">px</span><span class=\"mtk1\">; </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;jumbotron&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;text-success  text-center&quot;</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fa fa-user&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Profile Information</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;row&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;col-sm-6&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;well&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Id</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">UserID</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">br</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Email</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">Email</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">br</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Name</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">Name</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>Step 4. Add the following code in <strong>main.go</strong> for importing <strong>Goth</strong> and other packages :</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;html/template&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;log&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;net/http&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;sort&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;github.com/gorilla/pat&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;github.com/markbates/goth&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;github.com/markbates/goth/gothic&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;github.com/markbates/goth/providers/twitter&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span></code></pre>\n<p>Now we are ready to implement Twitter Authentication in our app</p>\n<p>Step 5. Setup the twitter configuration by adding the following code in <strong>main.go</strong> :</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">goth.</span><span class=\"mtk11\">UseProviders</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        twitter.</span><span class=\"mtk11\">New</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;TWITTER_KEY&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;TWITTER_SECRET&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;http://127.0.0.1:3000/auth/twitter/callback&quot;</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span></code></pre>\n<p>Step 6. For adding all routes and functionality you just need to add following code in <strong>main.go</strong> :</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ProviderIndex</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     Providers[]</span><span class=\"mtk14\"> </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     ProvidersMap </span><span class=\"mtk4\">map</span><span class=\"mtk1\">[</span><span class=\"mtk10\">string</span><span class=\"mtk1\">] </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     goth.</span><span class=\"mtk11\">UseProviders</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         twitter.</span><span class=\"mtk11\">New</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;TWITTER_KEY&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;TWITTER_SECRET&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;http://127.0.0.1:3000/auth/twitter/callback&quot;</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk3\">// If you&#39;d like to use authenticate instead of authorize in Twitter provider, use this instead.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk3\">// twitter.NewAuthenticate(os.Getenv(&quot;TWITTER_KEY&quot;), os.Getenv(&quot;TWITTER_SECRET&quot;), &quot;http://localhost:3000/auth/twitter/callback&quot;),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     )</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     m: = </span><span class=\"mtk11\">make</span><span class=\"mtk1\">(</span><span class=\"mtk4\">map</span><span class=\"mtk1\">[</span><span class=\"mtk10\">string</span><span class=\"mtk1\">] </span><span class=\"mtk10\">string</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     m[</span><span class=\"mtk8\">&quot;twitter&quot;</span><span class=\"mtk1\">] = </span><span class=\"mtk8\">&quot;Twitter&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> keys[]</span><span class=\"mtk14\"> </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> k: = </span><span class=\"mtk15\">range</span><span class=\"mtk1\"> m {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk12\">keys</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">append</span><span class=\"mtk1\">(keys, k)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     sort.</span><span class=\"mtk11\">Strings</span><span class=\"mtk1\">(keys)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     providerIndex: = & ProviderIndex {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         Providers: keys,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         ProvidersMap: m</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     p: = pat.</span><span class=\"mtk11\">New</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     p.</span><span class=\"mtk11\">Get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth/{provider}/callback&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">func</span><span class=\"mtk1\">(res http.ResponseWriter, req * http.Request) {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         user, err: = gothic.</span><span class=\"mtk11\">CompleteUserAuth</span><span class=\"mtk1\">(res, req)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             fmt.</span><span class=\"mtk11\">Fprintln</span><span class=\"mtk1\">(res, err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         t, _: = template.</span><span class=\"mtk11\">ParseFiles</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;templates/success.html&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         t.</span><span class=\"mtk11\">Execute</span><span class=\"mtk1\">(res, user)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     p.</span><span class=\"mtk11\">Get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/logout/{provider}&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">func</span><span class=\"mtk1\">(res http.ResponseWriter, req * http.Request) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         gothic.</span><span class=\"mtk11\">Logout</span><span class=\"mtk1\">(res, req)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         res.</span><span class=\"mtk11\">Header</span><span class=\"mtk1\">().</span><span class=\"mtk11\">Set</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Location&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         res.</span><span class=\"mtk11\">WriteHeader</span><span class=\"mtk1\">(http.StatusTemporaryRedirect)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     p.</span><span class=\"mtk11\">Get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth/{provider}&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">func</span><span class=\"mtk1\">(res http.ResponseWriter, req * http.Request) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk3\">// try to get the user without re-authenticating</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> gothUser, err: = gothic.</span><span class=\"mtk11\">CompleteUserAuth</span><span class=\"mtk1\">(res, req);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         err == </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             t, _: = template.</span><span class=\"mtk11\">ParseFiles</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;templates/success.html&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             t.</span><span class=\"mtk11\">Execute</span><span class=\"mtk1\">(res, gothUser)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         } </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             gothic.</span><span class=\"mtk11\">BeginAuthHandler</span><span class=\"mtk1\">(res, req)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     p.</span><span class=\"mtk11\">Get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">func</span><span class=\"mtk1\">(res http.ResponseWriter, req * http.Request) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         t, _: = template.</span><span class=\"mtk11\">ParseFiles</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;templates/index.html&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         t.</span><span class=\"mtk11\">Execute</span><span class=\"mtk1\">(res, providerIndex)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     log.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;listening on localhost:3000&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(http.</span><span class=\"mtk11\">ListenAndServe</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;:3000&quot;</span><span class=\"mtk1\">, p))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> }</span></span></code></pre>\n<p>Now you just need to run the project by using the following command and try logging by using the Twitter button.</p>\n<p>Step 7. Run the project :</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"> go run main.go</span></code></pre>\n<p>Step 8. Visit the browser with the URL <code>http://127.0.0.1:3000</code>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 25.846153846153847%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA2klEQVQY02WQ2Y7CIBSGff8XMHNpfJeZK5cLt8Ylbh0KtLVaq7EUfs8BmzEOycc5wMdh6YCacw61aVDXhqLx0dDYNYA1lnCBJuAd8+dy5BrcOtxZGqisgFAZhM4h9QkHKTE7brASRyxkIBJ7RPEOv+Ql5DG8R6UnWPtRUOdnL0haVGmBg5KYxGss9isMxz8YjL4x3UaYiy0dmnmvRefF/4LvN+SYqBxpUSGZrxF/9RF3e5CTJTTNeY/WW1d+3pDff63uuFwr4vaC8pKoKH/UAc7Ldyd4Jc23f/gEVVZ84B76xwwAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Login\"\n        title=\"Login\"\n        src=\"/static/1091ef65b568901c5a3905a0bc54dcde/e5715/login.png\"\n        srcset=\"/static/1091ef65b568901c5a3905a0bc54dcde/a6d36/login.png 650w,\n/static/1091ef65b568901c5a3905a0bc54dcde/e5715/login.png 768w,\n/static/1091ef65b568901c5a3905a0bc54dcde/e0202/login.png 1395w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>We need to click on <strong>Authorize button</strong>, which will redirect us to google login page  </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.61538461538462%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABJklEQVQoz5WS606EMBCF9/3fxIcxmmj2z25UAhSQcmkpLbSF49AogV3NrpMMJZn2mzM9PczzjG3SB8rSguuYpmld61bCWgvrXNj7c/5wBaToOomyyFHXNXhVQQgBrU2o8UaClVX4vzwbgGv7DTBOYzy+HnF+OyFjjBooeO9DLclLHM/RuncrZIkLhWEgvEQxHp4TPL1/YPLDbmxjDBpSrHpNTaYdcKdwWzBaoOIRqpqhbEq0bQshJcE99GgherOD3QR2qkfKCsocWZaDsYzuUQYDrJvQDw7+26D7gF2HOEmRpClBGfLiEz2NOI7jbvy7FfZaBwjnFaTsKGUY21r3q6qbQKUUSs7pDmu0ZMDisrXj+g7/DdSLk00TgAvMmAGj85vnhT+BX5btDqblzarnAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Auth\"\n        title=\"Auth\"\n        src=\"/static/8bdcd51ad3b4cf6ec56a1ea6dcb532a8/e5715/auth.png\"\n        srcset=\"/static/8bdcd51ad3b4cf6ec56a1ea6dcb532a8/a6d36/auth.png 650w,\n/static/8bdcd51ad3b4cf6ec56a1ea6dcb532a8/e5715/auth.png 768w,\n/static/8bdcd51ad3b4cf6ec56a1ea6dcb532a8/35252/auth.png 1204w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>After login with our twitter credentials, it will redirect back to our application and on the success page, we can see the details of the logged-in user and can save this detail in the database for future use also.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 26.307692307692303%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAuklEQVQY022QiQ6DIAxA/f/f22Hm1HnhAeiU6eYBdgUXFzebPErT5tFgAYaaZ3j1wx9yVIZpkAt4HzH/zvXDCDM6dFj6mKSEgt83ZKyEQ+wabBIYzokP1zSCgmGfljhTmaznpVJfocLCDxNwvAAJISI5pJTDiXhwRC5paLDJDdwsBsrrzeOsqo1jFWq744dGqMVaSHIGnAsD480KZfWyHa0+7GyoC9E+NzSPDmrR7qJ7K1iLtsMNlz98A+Y1fQ6eNSIpAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Profile\"\n        title=\"Profile\"\n        src=\"/static/6d22d851c81ed5411de7ec1098eeb2e7/e5715/profile.png\"\n        srcset=\"/static/6d22d851c81ed5411de7ec1098eeb2e7/a6d36/profile.png 650w,\n/static/6d22d851c81ed5411de7ec1098eeb2e7/e5715/profile.png 768w,\n/static/6d22d851c81ed5411de7ec1098eeb2e7/e40ed/profile.png 1378w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>As we have seen it is fairly easy to build a twitter social authentication system with Go  and Goth, You can found the complete code used in this tutorial on our<a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/GoLang/TwitterAuthenticationGoth\"> Github Repo</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk14 { color: #F44747; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"June 15, 2020","updated_date":null,"title":"Twitter authentication with Go Language and Goth","tags":["Go","SocialLogin","Oauth"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7699115044247788,"src":"/static/128533caa8a4ba717d200f38198342e4/14b42/cover.jpg","srcSet":"/static/128533caa8a4ba717d200f38198342e4/f836f/cover.jpg 200w,\n/static/128533caa8a4ba717d200f38198342e4/2244e/cover.jpg 400w,\n/static/128533caa8a4ba717d200f38198342e4/14b42/cover.jpg 800w,\n/static/128533caa8a4ba717d200f38198342e4/47498/cover.jpg 1200w,\n/static/128533caa8a4ba717d200f38198342e4/0e329/cover.jpg 1600w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Ashish Sharma","github":"ashish8947","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/google-authentication-with-golang-and-goth/"},"html":"<p>In this blog, we’ll be implementing authentication via Google in a Go web application. For this, we’ll be using <a href=\"https://github.com/markbates/goth\">Goth</a> - Multi-Provider Authentication Package for Go</p>\n<h2 id=\"before-you-get-started\" style=\"position:relative;\"><a href=\"#before-you-get-started\" aria-label=\"before you get started permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Before You Get Started</h2>\n<p>This tutorial assumes you have:</p>\n<ul>\n<li>Basic knowledge of HTML/CSS</li>\n<li>A basic understanding of Go Language</li>\n<li>Latest GoLang version installed on your system</li>\n</ul>\n<h3 id=\"step-1-create-a-google-client-id-and-client-secret\" style=\"position:relative;\"><a href=\"#step-1-create-a-google-client-id-and-client-secret\" aria-label=\"step 1 create a google client id and client secret permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 1: Create a Google client ID and client secret</h3>\n<p>We can create a  client ID and client secret using its <a href=\"https://console.developers.google.com/\">Google API Console</a>. You need to follow below steps once you open Google API Console</p>\n<ul>\n<li>From the project drop-down, select an existing project, or create a new one by selecting Create a new project</li>\n<li>In the sidebar under \"APIs &#x26; Services\", select Credentials</li>\n<li>In the Credentials tab, select the Create credentials drop-down list, and choose OAuth client ID.</li>\n<li>Under Application type, select Web application.</li>\n<li>In Authorized redirect URI use <code>http://localhost:3000/auth/google/callback</code></li>\n<li>Press the Create button and copy the generated client ID and client secret</li>\n</ul>\n<p><strong>Note:</strong> If Google doesn't support <code>http://localhost:3000</code>, then use <code>http://127.0.0.1:3000</code></p>\n<h3 id=\"step-2-initialize-a-go-project-using-go-modules\" style=\"position:relative;\"><a href=\"#step-2-initialize-a-go-project-using-go-modules\" aria-label=\"step 2 initialize a go project using go modules permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 2: Initialize a Go project using Go modules</h3>\n<p>First in an empty folder run the below command</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">go mod init googleauth</span></code></pre>\n<p><code>go mod init</code> creates a new go.mod file and automatically imports dependencies when you will run go program</p>\n<h3 id=\"step-3-writing-golang-server-code-to-accept-web-requests\" style=\"position:relative;\"><a href=\"#step-3-writing-golang-server-code-to-accept-web-requests\" aria-label=\"step 3 writing golang server code to accept web requests permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 3: Writing golang server code to accept web requests</h3>\n<p>Create a file <strong>main.go</strong> in the root folder of your app and add the following code: </p>\n<p>A small description for packages used in below code</p>\n<ul>\n<li><strong>gorilla/pat:</strong>  A lightweight HTTP router for Go</li>\n<li><strong>markbates/goth:</strong>  Multi-Provider Authentication Package for Go</li>\n<li><strong>gorilla/sessions:</strong>  To save information from google in session and use it on the success page</li>\n<li><strong>markbates/goth/providers/google:</strong>  Google authentication provider by Goth</li>\n<li><strong>html/template:</strong> Go package to parse Html files</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">package</span><span class=\"mtk1\"> main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;html/template&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;net/http&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;log&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;github.com/gorilla/pat&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;github.com/markbates/goth&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;github.com/markbates/goth/gothic&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;github.com/markbates/goth/providers/google&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;github.com/gorilla/sessions&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">key</span><span class=\"mtk1\"> := </span><span class=\"mtk8\">&quot;Secret-session-key&quot;</span><span class=\"mtk1\">  </span><span class=\"mtk3\">// Replace with your SESSION_SECRET or similar</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">maxAge</span><span class=\"mtk1\"> := </span><span class=\"mtk7\">86400</span><span class=\"mtk1\"> * </span><span class=\"mtk7\">30</span><span class=\"mtk1\">  </span><span class=\"mtk3\">// 30 days</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">isProd</span><span class=\"mtk1\"> := </span><span class=\"mtk4\">false</span><span class=\"mtk1\">       </span><span class=\"mtk3\">// Set to true when serving over https</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">store</span><span class=\"mtk1\"> := sessions.</span><span class=\"mtk11\">NewCookieStore</span><span class=\"mtk1\">([]</span><span class=\"mtk11\">byte</span><span class=\"mtk1\">(key))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  store.</span><span class=\"mtk11\">MaxAge</span><span class=\"mtk1\">(maxAge)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">store.Options.Path</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;/&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">store.Options.HttpOnly</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">true</span><span class=\"mtk1\">   </span><span class=\"mtk3\">// HttpOnly should always be enabled</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">store.Options.Secure</span><span class=\"mtk1\"> = isProd</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">gothic.Store</span><span class=\"mtk1\"> = store</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  goth.</span><span class=\"mtk11\">UseProviders</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    google.</span><span class=\"mtk11\">New</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;our-google-client-id&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;our-google-client-secret&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;http://localhost:3000/auth/google/callback&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;profile&quot;</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  )</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">p</span><span class=\"mtk1\"> := pat.</span><span class=\"mtk11\">New</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  p.</span><span class=\"mtk11\">Get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth/{provider}/callback&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">func</span><span class=\"mtk1\">(res http.ResponseWriter, req *http.Request) {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">user</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := gothic.</span><span class=\"mtk11\">CompleteUserAuth</span><span class=\"mtk1\">(res, req)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      fmt.</span><span class=\"mtk11\">Fprintln</span><span class=\"mtk1\">(res, err)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">t</span><span class=\"mtk1\">, </span><span class=\"mtk12\">_</span><span class=\"mtk1\"> := template.</span><span class=\"mtk11\">ParseFiles</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;templates/success.html&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    t.</span><span class=\"mtk11\">Execute</span><span class=\"mtk1\">(res, user)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  p.</span><span class=\"mtk11\">Get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth/{provider}&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">func</span><span class=\"mtk1\">(res http.ResponseWriter, req *http.Request) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    gothic.</span><span class=\"mtk11\">BeginAuthHandler</span><span class=\"mtk1\">(res, req)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  p.</span><span class=\"mtk11\">Get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">func</span><span class=\"mtk1\">(res http.ResponseWriter, req *http.Request) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">t</span><span class=\"mtk1\">, </span><span class=\"mtk12\">_</span><span class=\"mtk1\"> := template.</span><span class=\"mtk11\">ParseFiles</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;templates/index.html&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    t.</span><span class=\"mtk11\">Execute</span><span class=\"mtk1\">(res, </span><span class=\"mtk4\">false</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  log.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;listening on localhost:3000&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  log.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(http.</span><span class=\"mtk11\">ListenAndServe</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;:3000&quot;</span><span class=\"mtk1\">, p))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p><strong>Note:</strong> The callback URL in <code>google.New</code> should be the same as used in the google app configuration.</p>\n<p>If it is hard to understand the code, Here is the description of all the routes used in the code mentioned above</p>\n<ul>\n<li><strong>\"/\":</strong>  The root route will render the index.html page</li>\n<li><strong>/auth/{provider}:</strong>  When you click on SignIn button it will hit this route and <code>gothic.BeginAuthHandler</code> will redirect you to google authentication URL</li>\n<li><strong>/auth/{provider}/callback:</strong>  Once you have authenticated Google will send all the user details on this callback URL, and goth will save the info in session also which can be used in other routes also if needed</li>\n</ul>\n<h3 id=\"step-4-creating-a-login-and-profile-page\" style=\"position:relative;\"><a href=\"#step-4-creating-a-login-and-profile-page\" aria-label=\"step 4 creating a login and profile page permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 4: Creating a Login and Profile page</h3>\n<p>Create an html file under path <strong>templates/index.html</strong>, it will render into a nice looking social login page:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- </span><span class=\"mtk12\">templates</span><span class=\"mtk1\">/</span><span class=\"mtk12\">index</span><span class=\"mtk1\">.</span><span class=\"mtk12\">html</span><span class=\"mtk1\"> --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">doctype</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Google SignIn</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load bulma css --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load fontawesome --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        body        </span><span class=\"mtk4\">{</span><span class=\"mtk1\"> </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">-</span><span class=\"mtk12\">top</span><span class=\"mtk1\">:70</span><span class=\"mtk12\">px</span><span class=\"mtk1\">; </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;jumbotron text-center text-success&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fa fa-lock&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Social Authentication</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Login or Register with:</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/auth/google&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;btn btn-danger&quot;</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fa fa-google&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> SignIn with Google</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">a</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> </span></span></code></pre>\n<p>After it we will create an Html file under path <strong>templates/success.html</strong>, it will be used to show the user profile information we will get after authenticated by google</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- </span><span class=\"mtk12\">templates</span><span class=\"mtk1\">/</span><span class=\"mtk12\">success</span><span class=\"mtk1\">.</span><span class=\"mtk12\">html</span><span class=\"mtk1\"> --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">doctype</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Google SignIn</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load bulma css --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> &lt;!-- load fontawesome --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          body        </span><span class=\"mtk4\">{</span><span class=\"mtk1\"> </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">-</span><span class=\"mtk12\">top</span><span class=\"mtk1\">:70</span><span class=\"mtk12\">px</span><span class=\"mtk1\">; </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;jumbotron&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;text-success  text-center&quot;</span><span class=\"mtk17\">&gt;&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fa fa-user&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Profile Information</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;row&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;col-sm-6&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;well&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Id</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">UserID</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">br</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Email</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">Email</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">br</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Name</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">strong</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">: </span><span class=\"mtk4\">{</span><span class=\"mtk1\">{.</span><span class=\"mtk12\">Name</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p><strong>Note:</strong> Here we are also using bootstrap and font-awesome css to make our web pages look good. </p>\n<p>We have finished building our social login page, let's run the application by below command</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">go run main.go</span></code></pre>\n<p>Once our server is running, we can see our social login page on <code>http://localhost:3000/</code></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 26.153846153846157%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAFABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdyRLB//xAAWEAADAAAAAAAAAAAAAAAAAAAAEBH/2gAIAQEAAQUCIv/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABYQAAMAAAAAAAAAAAAAAAAAAAAQMf/aAAgBAQAGPwIq/8QAFxABAQEBAAAAAAAAAAAAAAAAAQARMf/aAAgBAQABPyHIR3UX/9oADAMBAAIAAwAAABB8P//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABkQAAMBAQEAAAAAAAAAAAAAAAABESExcf/aAAgBAQABPxB1dZa8mSC50//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Social Authentication Page\"\n        title=\"Social Authentication Page\"\n        src=\"/static/e9fbab976c1381bbef6c74a7e927f413/212bf/go_google_login.jpg\"\n        srcset=\"/static/e9fbab976c1381bbef6c74a7e927f413/6aca1/go_google_login.jpg 650w,\n/static/e9fbab976c1381bbef6c74a7e927f413/212bf/go_google_login.jpg 768w,\n/static/e9fbab976c1381bbef6c74a7e927f413/e2731/go_google_login.jpg 1462w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>We need to click on <strong>SignIn with Google button</strong>, which will redirect us to the google login page.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.61538461538462%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAMF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAd8mlQv/xAAWEAADAAAAAAAAAAAAAAAAAAAAIEP/2gAIAQEAAQUCSh//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAQIIH/2gAIAQEABj8CSD//xAAXEAADAQAAAAAAAAAAAAAAAAAAARAx/9oACAEBAAE/IWKrcf/aAAwDAQACAAMAAAAQLA//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPxBZ/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EA2f/8QAHBABAAEEAwAAAAAAAAAAAAAAAREAECExQWGB/9oACAEBAAE/EEBmlJue7PFJhliOPbf/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Google Login\"\n        title=\"Google Login\"\n        src=\"/static/50f7a7ff4ae46578ee72084f50d31297/212bf/google_login.jpg\"\n        srcset=\"/static/50f7a7ff4ae46578ee72084f50d31297/6aca1/google_login.jpg 650w,\n/static/50f7a7ff4ae46578ee72084f50d31297/212bf/google_login.jpg 768w,\n/static/50f7a7ff4ae46578ee72084f50d31297/68a11/google_login.jpg 1246w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>After login with our google credentials, it will redirect back to our application and on the success page, we can see the details of the logged-in user and can save this detail in a database for future use also.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 26.46153846153846%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAFABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdsJQX//xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAEFAn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAVEAEBAAAAAAAAAAAAAAAAAAAQMf/aAAgBAQAGPwKv/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERIWH/2gAIAQEAAT8hjr0Toj//2gAMAwEAAgADAAAAEHwP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxAAAgIDAQAAAAAAAAAAAAAAAAEhQRExUZH/2gAIAQEAAT8QmmxOuCwt6LGz/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Social Profile Info\"\n        title=\"Social Profile Info\"\n        src=\"/static/1c06a7df8d424efbab2c0a699a7549cd/212bf/go_google_profile.jpg\"\n        srcset=\"/static/1c06a7df8d424efbab2c0a699a7549cd/6aca1/go_google_profile.jpg 650w,\n/static/1c06a7df8d424efbab2c0a699a7549cd/212bf/go_google_profile.jpg 768w,\n/static/1c06a7df8d424efbab2c0a699a7549cd/e3298/go_google_profile.jpg 1473w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>As we have seen it is fairly easy to build a google social authentication system with Go language and Goth package, You can found the complete code used in this tutorial on our <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/GoLang/GoogleAuthenticationGoth\">Github Repo</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk17 { color: #808080; }\n</style>","frontmatter":{"date":"June 11, 2020","updated_date":null,"title":"Google OAuth2 Authentication in Golang","tags":["Go","SocialLogin","Oauth"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.6666666666666667,"src":"/static/cd7a60fb3610d7b93965f555bbdadc73/46604/google_golang.png","srcSet":"/static/cd7a60fb3610d7b93965f555bbdadc73/69585/google_golang.png 200w,\n/static/cd7a60fb3610d7b93965f555bbdadc73/497c6/google_golang.png 400w,\n/static/cd7a60fb3610d7b93965f555bbdadc73/46604/google_golang.png 500w","sizes":"(max-width: 500px) 100vw, 500px"}}},"author":{"id":"Puneet Singh","github":"puneetsingh24","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/custom-encoders-in-the-mongo-go-driver/"},"html":"<p>The official supported drivers for Mongo for Go have been officially released for several months now and is slowly seeing more usage. Although many of the features of standard Mongo drivers have been implemented within the supported driver, the documentation for a majority of the features are still in the process of being created. This post will provide some information on how to set up custom JSON encoders so you can change how BSON operators are processed whenever Mongo documents are marshalled into JSON. For this blog, a custom date and object id encoder will be created to handle the BSON operators and transform them into more easily processed JSON.</p>\n<p>This blog assumes that you have a basic understanding of Go and how to write some code in the language. If you want to follow along with the guide, you will also require a working Mongo instance, as well as your environment set up for Go.</p>\n<p>Before interacting with the database, we can set up a quick Go application that finds data from a Mongo database and outputs it. For this example, the Mongo database is set up with a collection containing documents with a name, a date and the object id. For our blog, the Mongo document that is being worked with is quite simple:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\"> : </span><span class=\"mtk11\">ObjectId</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;5de6b0850f3c7b5cce642529&quot;</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;Name&quot;</span><span class=\"mtk1\"> : </span><span class=\"mtk8\">&quot;dateOne&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;Date&quot;</span><span class=\"mtk1\"> : </span><span class=\"mtk11\">ISODate</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;2019-04-08T11:55:02.658Z&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>A simple main function that retrieves data from Mongo and outputs the JSON string is as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">result</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tID   primitive.ObjectID </span><span class=\"mtk8\">`bson:&quot;_id&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tName </span><span class=\"mtk10\">string</span><span class=\"mtk1\">             </span><span class=\"mtk8\">`bson:&quot;Name&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tDate primitive.DateTime </span><span class=\"mtk8\">`bson:&quot;Date&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">cancel</span><span class=\"mtk1\"> := context.</span><span class=\"mtk11\">WithTimeout</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">Background</span><span class=\"mtk1\">(), </span><span class=\"mtk7\">10</span><span class=\"mtk1\">*time.Second)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">client</span><span class=\"mtk1\">, </span><span class=\"mtk12\">connErr</span><span class=\"mtk1\"> := mongo.</span><span class=\"mtk11\">Connect</span><span class=\"mtk1\">(ctx, options.</span><span class=\"mtk11\">Client</span><span class=\"mtk1\">().</span><span class=\"mtk11\">ApplyURI</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> connErr != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tlog.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(connErr)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">collection</span><span class=\"mtk1\"> := client.</span><span class=\"mtk11\">Database</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;test&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">Collection</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;dates&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">filter</span><span class=\"mtk1\"> := bson.M{</span><span class=\"mtk8\">&quot;Name&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;dateOne&quot;</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">findErr</span><span class=\"mtk1\"> := collection.</span><span class=\"mtk11\">FindOne</span><span class=\"mtk1\">(ctx, filter).</span><span class=\"mtk11\">Decode</span><span class=\"mtk1\">(&result)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> findErr != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tlog.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(findErr)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tfmt.</span><span class=\"mtk11\">Print</span><span class=\"mtk1\">(result.Date)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">data</span><span class=\"mtk1\">, </span><span class=\"mtk12\">writeErr</span><span class=\"mtk1\"> := bson.</span><span class=\"mtk11\">MarshalExtJSON</span><span class=\"mtk1\">(result, </span><span class=\"mtk4\">false</span><span class=\"mtk1\">, </span><span class=\"mtk4\">false</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> writeErr != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tlog.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(writeErr)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tfmt.</span><span class=\"mtk11\">Print</span><span class=\"mtk1\">(</span><span class=\"mtk11\">string</span><span class=\"mtk1\">(data))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk11\">cancel</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The function MarshalExtJSON is a part of the bson package that is a part of the driver. It uses a default registry to define the rules when converting Mongo primitive types into JSON. The arguments it takes are the Go struct being passed in, whether the result should be returned in canonical form (For more details, check this <a href=\"https://docs.mongodb.com/manual/reference/mongodb-extended-json/%5D(https://docs.mongodb.com/manual/reference/mongodb-extended-json/)\">link</a>, and whether HTML strings are escaped.</p>\n<p>The output of this function when reading our document produces a JSON string with all the BSON operators included.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk8\">&quot;$oid&quot;</span><span class=\"mtk1\">:</span><span class=\"mtk8\">&quot;5de6b0850f3c7b5cce642529&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;Name&quot;</span><span class=\"mtk1\">:</span><span class=\"mtk8\">&quot;dateOne&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;Date&quot;</span><span class=\"mtk1\">:{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk8\">&quot;$date&quot;</span><span class=\"mtk1\">:</span><span class=\"mtk8\">&quot;2019-04-08T11:55:02.658Z&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Using custom encoders, we can change how the bson package marshals the JSON and remove all the BSON operators. The first thing to do is to define package level variables that will hold the types of the Mongo primitives that need to be changed in the JSON response. Outside the main function, include these two lines:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tOID</span><span class=\"mtk1\"> = reflect.</span><span class=\"mtk11\">TypeOf</span><span class=\"mtk1\">(primitive.ObjectID{})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tDateTime</span><span class=\"mtk1\"> = reflect.</span><span class=\"mtk11\">TypeOf</span><span class=\"mtk1\">(primitive.</span><span class=\"mtk11\">DateTime</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">))</span></span></code></pre>\n<p>Next, we can make new functions to customize how these types are handled. For the date encoding, we want to have the Date key matched with the returned date string.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">dateTimeEncodeValue</span><span class=\"mtk1\">(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) </span><span class=\"mtk10\">error</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">jDateFormat</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;2006-01-02T15:04:05.999Z&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> !val.</span><span class=\"mtk11\">IsValid</span><span class=\"mtk1\">() || val.</span><span class=\"mtk11\">Type</span><span class=\"mtk1\">() != tDateTime {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> bsoncodec.ValueEncoderError{Name: </span><span class=\"mtk8\">&quot;DateTimeEncodeValue&quot;</span><span class=\"mtk1\">, Types: []reflect.Type{tDateTime}, Received: val}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">ints</span><span class=\"mtk1\"> := val.</span><span class=\"mtk11\">Int</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">t</span><span class=\"mtk1\"> := time.</span><span class=\"mtk11\">Unix</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, ints*</span><span class=\"mtk7\">1000000</span><span class=\"mtk1\">).</span><span class=\"mtk11\">UTC</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> vw.</span><span class=\"mtk11\">WriteString</span><span class=\"mtk1\">(t.</span><span class=\"mtk11\">Format</span><span class=\"mtk1\">(jdateFormat))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The parameters in this function are pre-defined within the driver package of the driver. This involves passing in the BSON encoding context, the value writer and the value that is being processed. The value writer and the value are the parameters that we use within our function.</p>\n<p>First, we check if the value passed in is the correct type. If there is an issue with the value, then an error is thrown during the encoding. Next, we can set the format we want our date string to appear in, and process our value into a Go Time object. After that, we can use the value writer to write the formatted date into our JSON string.</p>\n<p>Similar to the custom date encoding, the object id encoding function has the same structure.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">objectIDEncodeValue</span><span class=\"mtk1\">(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) </span><span class=\"mtk10\">error</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> !val.</span><span class=\"mtk11\">IsValid</span><span class=\"mtk1\">() || val.</span><span class=\"mtk11\">Type</span><span class=\"mtk1\">() != tOID {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> bsoncodec.ValueEncoderError{Name: </span><span class=\"mtk8\">&quot;ObjectIDEncodeValue&quot;</span><span class=\"mtk1\">, Types: []reflect.Type{tOID}, Received: val}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">s</span><span class=\"mtk1\"> := val.</span><span class=\"mtk11\">Interface</span><span class=\"mtk1\">().(primitive.ObjectID).</span><span class=\"mtk11\">Hex</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> vw.</span><span class=\"mtk11\">WriteString</span><span class=\"mtk1\">(s)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>First, we check if the type is valid, and if it is, we simply write out the object id as a hex string. To create the hex string, we first convert the value into an interface, then cast it as an object id to allow the Hex function to be called.</p>\n<p>Now that our two functions are created to handle the BSON types, we can create our custom registry.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">createCustomRegistry</span><span class=\"mtk1\">() *bsoncodec.RegistryBuilder {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">primitiveCodecs</span><span class=\"mtk1\"> bson.PrimitiveCodecs</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">rb</span><span class=\"mtk1\"> := bsoncodec.</span><span class=\"mtk11\">NewRegistryBuilder</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        bsoncodec.DefaultValueEncoders{}.</span><span class=\"mtk11\">RegisterDefaultEncoders</span><span class=\"mtk1\">(rb)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        bsoncodec.DefaultValueDecoders{}.</span><span class=\"mtk11\">RegisterDefaultDecoders</span><span class=\"mtk1\">(rb)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\trb.</span><span class=\"mtk11\">RegisterEncoder</span><span class=\"mtk1\">(tDateTime, bsoncodec.</span><span class=\"mtk11\">ValueEncoderFunc</span><span class=\"mtk1\">(dateTimeEncodeValue))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\trb.</span><span class=\"mtk11\">RegisterEncoder</span><span class=\"mtk1\">(tOID, bsoncodec.</span><span class=\"mtk11\">ValueEncoderFunc</span><span class=\"mtk1\">(objectIDEncodeValue))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tprimitiveCodecs.</span><span class=\"mtk11\">RegisterPrimitiveCodecs</span><span class=\"mtk1\">(rb)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> rb</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>In this function, we are setting up our registry to use our custom encoders, while also setting up default encoders for all other types that are being marshalled. Using the bsoncodec package, the NewRegistryBuilder function is called to initialize a new registry. Next, we set up this registry with the default encoders and decoders that are pre-programmed in the driver using RegisterDefaultEncoders. During this step, we can also register encoders and decoders for raw types by calling RegisterPrimitiveCodecs. Finally, we can include our custom encoders by calling RegisterEncoder on the custom registry struct. Our encoder will be called whenever the type defined in the first argument in RegisterEncoder is found in the struct being marshalled.</p>\n<p>To ensure our new custom registry is being used, we have to do two things. The first is to build the custom registry. This should be done before the marshalling of the struct.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">customRegistry</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">createCustomRegistry</span><span class=\"mtk1\">().</span><span class=\"mtk11\">Build</span><span class=\"mtk1\">()</span></span></code></pre>\n<p>Next, we need to change the marshalling method to use the new custom registry instead of the default one. We can do this by changing the method being used to marshal the struct.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">customData</span><span class=\"mtk1\">, </span><span class=\"mtk12\">writeErr</span><span class=\"mtk1\"> := bson.</span><span class=\"mtk11\">MarshalExtJSONWithRegistry</span><span class=\"mtk1\">(customRegistry, result, </span><span class=\"mtk4\">false</span><span class=\"mtk1\">, </span><span class=\"mtk4\">false</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>The function MarshalExtJSONWithRegistry takes the same parameters as MarshalExtJSON, but also requires a custom registry to be passed in as the first parameter. We pass in the custom registry we created into the method to allow the marshalling to use our custom encoders. As a result, when printing our new JSON string output, we get this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span><span class=\"mtk8\">&quot;_id&quot;</span><span class=\"mtk1\">:</span><span class=\"mtk8\">&quot;5de6b0850f3c7b5cce642529&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk8\">&quot;Name&quot;</span><span class=\"mtk1\">:</span><span class=\"mtk8\">&quot;dateOne&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk8\">&quot;Date&quot;</span><span class=\"mtk1\">:</span><span class=\"mtk8\">&quot;2019-04-08T11:55:02.658Z&quot;</span><span class=\"mtk1\">}</span></span></code></pre>\n<p>The Mongo driver for Go is still in active development and new versions continue to be released. Hopefully this blog provides some useful information on how the driver works while new documentation is being created.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"December 03, 2019","updated_date":null,"title":"Custom Encoders in the Mongo Go Driver","tags":["Go","Golang","MongoDriver"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.25,"src":"/static/0bf88d6b53aaaf119a2556b41f4c8383/ee604/mongo-drivers.png","srcSet":"/static/0bf88d6b53aaaf119a2556b41f4c8383/69585/mongo-drivers.png 200w,\n/static/0bf88d6b53aaaf119a2556b41f4c8383/497c6/mongo-drivers.png 400w,\n/static/0bf88d6b53aaaf119a2556b41f4c8383/ee604/mongo-drivers.png 800w,\n/static/0bf88d6b53aaaf119a2556b41f4c8383/30c15/mongo-drivers.png 936w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Chris Yee","github":null,"avatar":null}}}}]}},"pageContext":{"tag":"Go"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}