<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[pratikjagrut.space]]></title><description><![CDATA[pratikjagrut.space]]></description><link>https://pratikjagrut.space</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 09:49:14 GMT</lastBuildDate><atom:link href="https://pratikjagrut.space/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Kubernetes: Deployments (Part-1)]]></title><description><![CDATA[Introduction
In the previous blog, we explored ReplicaSets and their importance in maintaining multiple identical pods for high application availability. However, in Kubernetes, we typically don't create ReplicaSets directly. Instead, we create highe...]]></description><link>https://pratikjagrut.space/kubernetes-deployments-part-1</link><guid isPermaLink="true">https://pratikjagrut.space/kubernetes-deployments-part-1</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[deployment]]></category><category><![CDATA[Devops]]></category><category><![CDATA[containers]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Mon, 15 Jul 2024 15:14:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1720500758403/39beff73-4ceb-45b2-bad0-429152628ef6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In the previous blog, we explored ReplicaSets and their importance in maintaining multiple identical pods for high application availability. However, in Kubernetes, we typically don't create ReplicaSets directly. Instead, we create higher-level objects such as Deployments, DaemonSets, or StatefulSets, which in turn manage ReplicaSets for us. In this blog, we'll delve into Deployments</p>
<p>Deployments are a crucial higher-level resource in Kubernetes, designed to manage the deployment and scaling of ReplicaSets, ensuring applications are always running in the desired state. We describe the desired state in the deployment configuration, and then the Deployment controller works to make the current state match the desired state.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721055695619/0d4a935c-59ea-4327-b65d-73b091838e33.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-difference-between-deployments-and-replicasets">Difference Between Deployments and ReplicaSets</h2>
<p>Deployments and ReplicaSets have different roles in Kubernetes. A ReplicaSet ensures a specified number of pod replicas are always running, but it lacks advanced update features. Deployments, however, allow for easy updates and rollbacks for pods and ReplicaSets. They support rolling updates and rollbacks. While ReplicaSets keep the right number of pods running, Deployments help manage application lifecycles, updates, and scaling without downtime, making them the better choice for managing stateless applications in Kubernetes.</p>
<h2 id="heading-configuring-a-deployment">Configuring a Deployment</h2>
<p>Configuring a Deployment involves defining a YAML file that specifies the desired state of the application. This includes details such as the application's image, the number of replicas, any necessary secrets and ConfigMaps, and a strategy for updating the application, ensuring smooth transitions with minimal downtime. Once the configuration file is applied, the Deployment controller works to ensure that the actual state matches the desired state.</p>
<p>Below is a sample YAML configuration for a Deployment:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-deployment</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:latest</span>
        <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>
  <span class="hljs-attr">strategy:</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">RollingUpdate</span>
    <span class="hljs-attr">rollingUpdate:</span>
      <span class="hljs-attr">maxUnavailable:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">maxSurge:</span> <span class="hljs-number">1</span>
</code></pre>
<h2 id="heading-breakdown-of-the-yaml-file">Breakdown of the YAML File</h2>
<p>When writing any object in Kubernetes, you need to include certain required fields: <code>apiVersion</code>, <code>kind</code>, <code>metadata</code>, and <code>spec</code>.</p>
<ol>
<li><p><strong>apiVersion:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
</code></pre>
<p> This field specifies the version of the Kubernetes API that your object adheres to, ensuring compatibility with your Kubernetes cluster. In this case, it uses <code>apps/v1</code>.</p>
</li>
<li><p><strong>kind:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
</code></pre>
<p> This field defines the type of Kubernetes object being created. In our YAML file, it indicates that we are creating a <code>Deployment</code>.</p>
</li>
<li><p><strong>metadata:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-deployment</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
</code></pre>
<p> This section provides essential information about the Deployment:</p>
<ul>
<li><p><strong>name:</strong> This uniquely identifies the Deployment within its namespace (<code>nginx-deployment</code>). This is the only required field in <code>metadata</code>.</p>
</li>
<li><p><strong>labels:</strong> Key-value pairs used to organize and select resources (<code>app: nginx</code>).</p>
</li>
</ul>
</li>
<li><p><strong>spec:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>
   <span class="hljs-attr">strategy:</span>
     <span class="hljs-attr">type:</span> <span class="hljs-string">RollingUpdate</span>
     <span class="hljs-attr">rollingUpdate:</span>
       <span class="hljs-attr">maxUnavailable:</span> <span class="hljs-number">1</span>
       <span class="hljs-attr">maxSurge:</span> <span class="hljs-number">1</span>
</code></pre>
<p> The <code>spec</code> section defines the desired state of the Deployment, including its pods and their configurations:</p>
<ul>
<li><p><strong>replicas:</strong> Specifies the number of pod replicas that the Deployment should maintain (3 in this case).</p>
</li>
<li><p><strong>selector:</strong> Defines how the Deployment identifies the pods it manages.</p>
<ul>
<li><strong>matchLabels:</strong> A set of key-value pairs used to match the pods (<code>app: nginx</code>). This should be the same as the labels in <code>template.metadata.labels</code>.</li>
</ul>
</li>
<li><p><strong>template:</strong> Describes the pod's configuration to be created.</p>
<ul>
<li><p><strong>metadata:</strong> Includes labels to be applied to the pods.</p>
</li>
<li><p><strong>spec:</strong> Defines the pod's configuration.</p>
<ul>
<li><p><strong>containers:</strong> Lists the containers within the pod.</p>
<ul>
<li><p><strong>name:</strong> Identifies the container (<code>nginx</code>).</p>
</li>
<li><p><strong>image:</strong> Specifies the Docker image to use (<code>nginx:latest</code>).</p>
</li>
<li><p><strong>ports:</strong> Indicates which ports should be exposed by the container (<code>containerPort: 80</code>).</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>strategy:</strong> Defines the strategy for updating the Deployment.</p>
<ul>
<li><p><strong>type:</strong> Specifies the update strategy. In this case, it is <code>RollingUpdate</code>, which updates pods in a rolling fashion with minimal downtime.</p>
</li>
<li><p><strong>rollingUpdate:</strong> Specifies parameters for the rolling update strategy, such as <code>maxUnavailable</code> and <code>maxSurge</code>.</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="heading-creating-a-deployment">Creating a Deployment</h2>
<p>To create a Deployment using the above YAML configuration, save the configuration to a file named <code>nginx-deployment.yaml</code> and apply it to the Kubernetes cluster using the following command:</p>
<pre><code class="lang-bash">kubectl apply -f nginx-deployment.yaml
</code></pre>
<h2 id="heading-managing-a-deployment">Managing a Deployment</h2>
<p>You can list the Deployments using the <code>kubectl get deployments</code> command:</p>
<pre><code class="lang-bash">kubectl get deployments
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           10s
</code></pre>
<p>You can use the <code>kubectl describe</code> command to check the state of the Deployment:</p>
<pre><code class="lang-bash">❯ kubectl describe deployments.apps/nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Mon, 15 Jul 2024 20:04:25 +0530
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:latest
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  &lt;none&gt;
    Mounts:       &lt;none&gt;
  Volumes:        &lt;none&gt;
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  &lt;none&gt;
NewReplicaSet:   nginx-deployment-57d84f57dc (3/3 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  54s   deployment-controller  Scaled up replica <span class="hljs-built_in">set</span> nginx-deployment-57d84f57dc to 3
</code></pre>
<p>List the ReplicaSets:</p>
<pre><code class="lang-bash">❯ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-57d84f57dc   3         3         3       93s
</code></pre>
<p>List the pods:</p>
<pre><code class="lang-bash">❯ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-57d84f57dc-w5n9r   1/1     Running   0          2m11s
nginx-deployment-57d84f57dc-8mf7x   1/1     Running   0          2m11s
nginx-deployment-57d84f57dc-gv24t   1/1     Running   0          2m11s
</code></pre>
<h3 id="heading-scaling-the-deployment">Scaling the Deployment</h3>
<p>You can scale the Deployment to a different number of replicas using the <code>kubectl scale</code> command:</p>
<pre><code class="lang-bash">❯ kubectl scale --replicas=5 deployment nginx-deployment
deployment.apps/nginx-deployment scaled
</code></pre>
<pre><code class="lang-bash">❯ kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   5/5     5            5           4m11s
</code></pre>
<pre><code class="lang-bash">❯ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-57d84f57dc-w5n9r   1/1     Running   0          4m24s
nginx-deployment-57d84f57dc-8mf7x   1/1     Running   0          4m24s
nginx-deployment-57d84f57dc-gv24t   1/1     Running   0          4m24s
nginx-deployment-57d84f57dc-9gjph   1/1     Running   0          27s
nginx-deployment-57d84f57dc-t47qd   1/1     Running   0          27s
</code></pre>
<h3 id="heading-deleting-the-deployment">Deleting the Deployment</h3>
<p>To delete the Deployment, use the following command:</p>
<pre><code class="lang-bash">kubectl delete deployment nginx-deployment
</code></pre>
<p>Deleting the Deployment will terminate all the pods it manages. If you want to keep the pods running after deleting the Deployment, use the <code>--cascade=orphan</code> flag:</p>
<pre><code class="lang-bash">kubectl delete deployment nginx-deployment --cascade=orphan
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, Deployments play a crucial role in managing the desired state of your applications by ensuring a specified number of pod replicas are running at all times. This not only enhances the availability and reliability of your applications but also simplifies the management of pods in a Kubernetes environment.</p>
<p>By defining a Deployment through a YAML file, you can easily control the number of replicas, monitor their status, and scale them as needed, ensuring your applications remain resilient and performant.</p>
<p><strong><em>Thank you for reading this blog; your interest is greatly appreciated. I hope this information helps you on your Kubernetes journey. In the next part, we'll explore updating and rolling back Kubernetes deployments.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Kubernetes: ReplicaSet]]></title><description><![CDATA[Introduction
In the last blog, we explored Pods and how they encapsulate containers to run workloads on Kubernetes. While Pods provide useful features for running workloads, they also have inherent issues due to their ephemeral nature—they can be ter...]]></description><link>https://pratikjagrut.space/kubernetes-replicaset</link><guid isPermaLink="true">https://pratikjagrut.space/kubernetes-replicaset</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[replicaset]]></category><category><![CDATA[cka]]></category><category><![CDATA[ckad]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Sun, 07 Jul 2024 11:32:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1720500826898/210785bd-9840-43f7-8b2c-6114919e1e4e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In the last blog, we explored Pods and how they encapsulate containers to run workloads on Kubernetes. While Pods provide useful features for running workloads, they also have inherent issues due to their ephemeral nature—they can be terminated at any time. When this happens, the user application will no longer be available.</p>
<p>To avoid such situations and ensure the user application is always available, Kubernetes uses <code>ReplicaSets (RS)</code>. A ReplicaSet creates multiple identical replicas of a pod and ensures a specific number of pods are running at all times—neither fewer nor more.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720501042183/2c464dcc-2159-4f8f-bf5f-5d74b6192978.png" alt class="image--center mx-auto" /></p>
<p>A <code>ReplicaSet controller</code> continuously monitors the pods to ensure that the number of desired pods equals the number of available pods at all times. If a pod fails, the ReplicaSet automatically creates more pods. Conversely, if new pods with the same label are added and there are more pods than needed, the ReplicaSet will reduce the number by stopping the extra pods.</p>
<h2 id="heading-configuring-a-replicaset">Configuring a ReplicaSet</h2>
<p>Configuring a ReplicaSet involves defining a YAML file that specifies the desired state for the ReplicaSet. This YAML file includes crucial details such as the number of replicas, the selector to identify the pods managed by the ReplicaSet, and the pod template that defines the pods to be created.</p>
<p>Below is a sample YAML configuration for a ReplicaSet using an Nginx container:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">ReplicaSet</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-replicaset</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-rs</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-pods</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-pods</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:latest</span>
        <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>
</code></pre>
<h3 id="heading-breakdown-of-the-yaml-file">Breakdown of the YAML File</h3>
<p>When writing any object in Kubernetes, you need to include certain required fields: <code>apiVersion</code>, <code>kind</code>, <code>metadata</code>, and <code>spec</code>.</p>
<ol>
<li><p><strong>apiVersion:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
</code></pre>
<p> This field specifies the version of the Kubernetes API that your object adheres to, ensuring compatibility with your Kubernetes cluster. In this case, it uses <code>apps/v1</code>.</p>
</li>
<li><p><strong>kind:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">kind:</span> <span class="hljs-string">ReplicaSet</span>
</code></pre>
<p> This field defines the type of Kubernetes object being created. In our YAML file, it indicates that we are creating a <code>ReplicaSet</code>.</p>
</li>
<li><p><strong>metadata:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-replicaset</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-rs</span>
</code></pre>
<p> This section provides essential information about the ReplicaSet:</p>
<ul>
<li><p><strong>name:</strong> This uniquely identifies the ReplicaSet within its namespace (<code>nginx-replicaset</code>). This is the only field in <code>metadata</code> that is required.</p>
</li>
<li><p><strong>namespace:</strong> Assigns a specific namespace for resource isolation (optional).</p>
</li>
<li><p><strong>labels:</strong> Key-value pairs used to organize and select resources (<code>app: nginx-rs</code>).</p>
</li>
<li><p><strong>annotations:</strong> These key-value pairs offer additional details about the Pod, useful for documentation, debugging, or monitoring (optional).</p>
</li>
<li><p><strong>ownerReferences:</strong> Specifies the controller managing the Pod, establishing a relationship hierarchy among Kubernetes resources (optional).</p>
</li>
</ul>
</li>
<li><p><strong>spec:</strong></p>
<pre><code class="lang-yaml"> <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-pods</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">nginx-pods</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>
</code></pre>
<p> The <code>spec</code> section defines the desired state of the ReplicaSet, including its pods and their configurations:</p>
<ul>
<li><p><strong>replicas:</strong> Specifies the number of pod replicas that the ReplicaSet should maintain (3 in this case).</p>
</li>
<li><p><strong>selector:</strong> Defines how the ReplicaSet identifies the pods it manages.</p>
<ul>
<li><p><strong>matchLabels:</strong> A set of key-value pairs used to match the pods (<code>app: nginx-pods</code>). This should be the same as the labels in <code>template.metadata.labels</code>.</p>
</li>
<li><p><strong>template:</strong> Describes the pod's configuration to be created.</p>
<ul>
<li><p><strong>metadata:</strong> Includes labels to be applied to the pods.</p>
</li>
<li><p><strong>spec:</strong> Defines the pod's configuration.</p>
<ul>
<li><p><strong>containers:</strong> Lists the containers within the pod.</p>
<ul>
<li><p><strong>name:</strong> Identifies the container (<code>nginx</code>).</p>
</li>
<li><p><strong>image:</strong> Specifies the Docker image to use (<code>nginx:latest</code>).</p>
</li>
<li><p><strong>ports:</strong> Indicates which ports should be exposed by the container (<code>containerPort: 80</code>).</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>        Additional optional fields for advanced configurations within the <code>spec</code> section include:</p>
<ul>
<li><p><strong>resources:</strong> Manages the pod's resource requests and limits.</p>
</li>
<li><p><strong>volumeMounts:</strong> Specifies volumes to be mounted into the container's filesystem.</p>
</li>
<li><p><strong>env:</strong> Defines environment variables accessible to the container.</p>
</li>
<li><p><strong>volumes:</strong> Describes persistent storage volumes available to the pod.</p>
</li>
</ul>
<h2 id="heading-creating-a-replicaset">Creating a ReplicaSet</h2>
<p>To create a ReplicaSet using the above YAML configuration, save the configuration to a file named <code>nginx-replicaset.yaml</code> and apply it to the Kubernetes cluster using the following command:</p>
<pre><code class="lang-bash">kubectl apply -f nginx-replicaset.yaml
</code></pre>
<h2 id="heading-managing-replicaset">Managing ReplicaSet</h2>
<p>You can list the replica sets using <code>kubectl get replicaset</code> command.</p>
<pre><code class="lang-bash">❯ kubectl get replicasets
NAME               DESIRED   CURRENT   READY   AGE
nginx-replicaset   3         3         3       2m17s
</code></pre>
<p>You can use the <code>kubectl describe</code> command to check the state of the replica set.</p>
<pre><code class="lang-bash">❯ kubectl describe replicasets.apps/nginx-replicaset
Name:         nginx-replicaset
Namespace:    default
Selector:     app=nginx-pods
Labels:       app=nginx-rs
Annotations:  &lt;none&gt;
Replicas:     3 current / 3 desired
Pods Status:  3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx-pods
  Containers:
   nginx:
    Image:        nginx:latest
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  &lt;none&gt;
    Mounts:       &lt;none&gt;
  Volumes:        &lt;none&gt;
Events:
  Type    Reason            Age   From                   Message
  ----    ------            ----  ----                   -------
  Normal  SuccessfulCreate  13s   replicaset-controller  Created pod: nginx-replicaset-rgxzx
  Normal  SuccessfulCreate  13s   replicaset-controller  Created pod: nginx-replicaset-prddh
  Normal  SuccessfulCreate  13s   replicaset-controller  Created pod: nginx-replicaset-rwvpn
</code></pre>
<p>You can list the pods using <code>kubectl get pods</code> command.</p>
<pre><code class="lang-bash">❯ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-replicaset-xqcjm   1/1     Running   0          10s
nginx-replicaset-pzzhh   1/1     Running   0          10s
nginx-replicaset-k4lp4   1/1     Running   0          10s/
</code></pre>
<h3 id="heading-scaling-the-replicaset"><strong>Scaling the ReplicaSet</strong></h3>
<p>You can scale the ReplicaSet to a different number of replicas using the <code>kubectl scale</code> command:</p>
<pre><code class="lang-bash">❯ kubectl scale --replicas=5 replicaset nginx-replicaset
replicaset.apps/nginx-replicaset scaled

❯ kubectl get replicasets
NAME               DESIRED   CURRENT   READY   AGE
nginx-replicaset   5         5         3       17m

❯ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-replicaset-xqcjm   1/1     Running   0          17m
nginx-replicaset-pzzhh   1/1     Running   0          17m
nginx-replicaset-k4lp4   1/1     Running   0          17m
nginx-replicaset-79d96   1/1     Running   0          16s
nginx-replicaset-sdb5g   1/1     Running   0          16s
</code></pre>
<h3 id="heading-updating-the-replicaset">Updating the ReplicaSet</h3>
<p>To update the ReplicaSet, such as changing the container image, you can modify the YAML file and apply the changes using:</p>
<pre><code class="lang-bash">kubectl apply -f nginx-replicaset.yaml
</code></pre>
<p>Alternatively, use the <code>kubectl set image</code> command to update the image directly:</p>
<pre><code class="lang-bash">kubectl <span class="hljs-built_in">set</span> image replicaset/nginx-replicaset nginx=nginx:1.19
</code></pre>
<h3 id="heading-deleting-the-replicaset"><strong>Deleting the ReplicaSet</strong></h3>
<p>To delete the ReplicaSet, use the following command:</p>
<pre><code class="lang-bash">kubectl delete rs nginx-replicaset
</code></pre>
<p>Deleting the ReplicaSet will terminate all the pods it manages. If you want to keep the pods running after deleting the ReplicaSet, use the <code>--cascade=orphan</code> flag:</p>
<pre><code class="lang-bash">kubectl delete rs nginx-replicaset --cascade=orphan
</code></pre>
<h2 id="heading-scenarios-where-rs-are-useful">Scenarios where RS are useful</h2>
<ol>
<li><p><strong>High Availability:</strong> ReplicaSets ensure that a specified number of pod replicas are always running, which is crucial for applications requiring high availability.</p>
</li>
<li><p><strong>Load Balancing:</strong> By maintaining multiple replicas of a pod, ReplicaSets help distribute the load evenly across all replicas, improving performance and reliability.</p>
</li>
<li><p><strong>Fault Tolerance:</strong> If a pod fails, the ReplicaSet automatically replaces it, ensuring continuous availability of the application.</p>
</li>
<li><p><strong>Rolling Updates:</strong> ReplicaSets can be used to perform rolling updates to applications, allowing updates without downtime by incrementally replacing old pods with new ones.</p>
</li>
<li><p><strong>Scalability:</strong> Easily scale the number of pod replicas up or down based on demand, ensuring efficient use of resources.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, ReplicaSets play a crucial role in maintaining the desired state of your applications by ensuring a specified number of pod replicas are running at all times. This not only enhances the availability and reliability of your applications but also simplifies the management of pods in a Kubernetes environment.</p>
<p><strong>Benefits of Using ReplicaSets:</strong></p>
<ul>
<li><p><strong>Enhanced Reliability:</strong> Ensures continuous application availability by maintaining multiple pod replicas.</p>
</li>
<li><p><strong>Improved Uptime:</strong> Automatically replaces failed pods to maintain the desired number of running pods.</p>
</li>
<li><p><strong>Simplified Scaling:</strong> Allows easy scaling of applications by adjusting the number of replicas.</p>
</li>
<li><p><strong>Consistent Performance:</strong> Distributes the load evenly across replicas, maintaining application performance.</p>
</li>
</ul>
<p>By defining a ReplicaSet through a YAML file, you can easily control the number of replicas, monitor their status, and scale them as needed, ensuring your applications remain resilient and performant.</p>
<p><strong><em>Thank you for reading this blog; your interest is greatly appreciated. I hope this information helps you on your Kubernetes journey. In the next blog, we'll explore Kubernetes deployments.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Kubernetes Pod 101]]></title><description><![CDATA[Introduction
With Kubernetes, our main goal is to run our application in a container. However, Kubernetes does not run the container directly on the cluster. Instead, it creates a Pod that encapsulates the container.

A Pod is the smallest object tha...]]></description><link>https://pratikjagrut.space/kubernetes-pod-101</link><guid isPermaLink="true">https://pratikjagrut.space/kubernetes-pod-101</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[#Pods ]]></category><category><![CDATA[cka]]></category><category><![CDATA[ckad]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[containers]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Thu, 27 Jun 2024 08:28:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1719318023755/05ac3393-6f8f-481b-b50a-a9e1933a3421.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>With Kubernetes, our main goal is to run our application in a container. However, Kubernetes does not run the container directly on the cluster. Instead, it creates a Pod that encapsulates the container.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719319106324/a556ddf2-677f-4698-8714-910c500bfbc8.png" alt class="image--center mx-auto" /></p>
<p><code>A Pod is the smallest object that you create and manage in Kubernetes.</code> A Pod consists of one or more containers that share storage and network resources, all running within a shared context. This shared context includes Linux namespaces, cgroups, and other isolation mechanisms, similar to those used for individual containers.</p>
<p>In a Kubernetes cluster, Pods use two models to run containers.:</p>
<ol>
<li><p><strong><em>One-container-per-Pod model</em></strong>: This is the common use case in Kubernetes. A Pod acts as a wrapper for a container, with Kubernetes managing the Pod instead of the individual container. <em>Refer to diagram POD-A.</em></p>
</li>
<li><p><strong><em>Multi-containers Pod model:</em></strong> Pods can run multiple containers that work closely together. These Pods hold applications made up of several containers that need to share resources and work closely. These containers operate as a single unit within the Pod. <em>Refer to diagram POD-B.</em></p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719291924908/1fa88102-3fb9-47aa-a9d0-813637e7ae48.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-anatomy-of-a-pod">Anatomy of a Pod</h2>
<h3 id="heading-containers">Containers</h3>
<p><strong>Main Container</strong></p>
<ul>
<li><p><strong>Primary Role:</strong> This is the application's primary container.</p>
</li>
<li><p><strong>Example:</strong> If you have a web application, the main container will run the web server that serves your application.</p>
</li>
</ul>
<p><strong>Sidecar Containers</strong></p>
<ul>
<li><p><strong>Supporting Role:</strong> These auxiliary containers support the main container, often used for logging, monitoring, or proxying tasks.</p>
</li>
<li><p><strong>Example:</strong> For the same web application, a sidecar container might handle logging by collecting and storing log data generated by the web server.</p>
</li>
</ul>
<h3 id="heading-storage-volumes">Storage (Volumes)</h3>
<p>Pods can include storage resources known as volumes, which enable data persistence across container restarts. Volumes in a Pod are shared among all containers in that Pod, allowing for data exchange between them.</p>
<ul>
<li><p><strong>Types of Volumes:</strong></p>
<ul>
<li><p><strong>emptyDir:</strong> A temporary directory that is created when a Pod is assigned to a node and deleted when the Pod is removed.</p>
</li>
<li><p><strong>hostPath:</strong> Maps a file or directory from the host node’s filesystem into a Pod.</p>
</li>
<li><p><strong>persistentVolumeClaim:</strong> A request for storage by a user that binds to a PersistentVolume (PV) in the cluster.</p>
</li>
<li><p><strong>configMap:</strong> Provides configuration data, command-line arguments, environment variables, or container files.</p>
</li>
<li><p><strong>secret:</strong> Used to store sensitive data such as passwords, OAuth tokens, and SSH keys.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-network">Network</h3>
<p>Each Pod is assigned a <code>unique IP address</code>. Containers within the same Pod share the network namespace, which means they can communicate with each other using <code>localhost</code>. Pods can communicate with each other using their assigned IP addresses.</p>
<ul>
<li><p><strong>Pod IP:</strong> A unique IP address assigned to each Pod.</p>
</li>
<li><p><strong>DNS:</strong> Kubernetes automatically assigns DNS names to Pods and services, facilitating network communication within the cluster.</p>
</li>
</ul>
<h3 id="heading-pod-lifecycle">Pod Lifecycle</h3>
<p>Like individual application containers, Pods are considered to be relatively temporary (rather than permanent) entities. Understanding the lifecycle of a Pod is crucial for effective management and troubleshooting.</p>
<p>Pods can be in one of several phases during their lifecycle. A Pod's <code>status</code> field is a <code>PodStatus</code> object, which has a <code>phase</code> field. The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle.</p>
<ul>
<li><p><strong>Pending:</strong> The Pod has been accepted by the Kubernetes system but one or more container images have not been created.</p>
</li>
<li><p><strong>Running:</strong> The Pod has been bound to a node, and all of the containers have been created. At least one container is still running or is in the process of starting or restarting.</p>
</li>
<li><p><strong>Succeeded:</strong> All containers in the Pod have terminated successfully, and the Pod will not be restarted.</p>
</li>
<li><p><strong>Failed:</strong> All containers in the Pod have terminated, and at least one container has terminated in failure.</p>
</li>
<li><p><strong>Unknown:</strong> The state of the Pod cannot be obtained, typically due to an error in communicating with the node where the Pod resides.</p>
</li>
</ul>
<h3 id="heading-pod-conditions">Pod Conditions</h3>
<p>Pods have a set of conditions that describe their current state. These conditions are used to diagnose and troubleshoot the status of Pods.</p>
<ul>
<li><p><strong>PodScheduled:</strong> Indicates whether the Pod has been scheduled to a node.</p>
</li>
<li><p><strong>Initialized:</strong> All init containers have been completed successfully.</p>
</li>
<li><p><strong>Ready:</strong> The Pod can serve requests and should be added to the load-balancer pools of all matching Services.</p>
</li>
<li><p><strong>ContainersReady:</strong> All containers in the Pod are ready.</p>
</li>
<li><p><strong>PodReadyToStartContainers</strong>: (beta feature; enabled by default) The Pod sandbox has been successfully created and networking configured.</p>
</li>
</ul>
<h2 id="heading-pod-creation">Pod creation</h2>
<p>A Pod can be created using two methods. The first method is by using the <code>kubectl run</code> command.</p>
<pre><code class="lang-bash">kubectl run --image nginx nginx-pod
</code></pre>
<p>The second method is declarative. In this approach, you create a Pod configuration file in YAML and apply it using the <code>kubectl create</code> or <code>kubectl apply</code> command. This method is widely used because it allows you to manage multiple versions of an application easily.</p>
<p>Create a configuration file named <code>nginx-pod.yaml</code> with the following content.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> 
<span class="hljs-attr">kind:</span> 
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-pod</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">nginx</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">containers:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">nginx-container</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">nginx:latest</span>
    <span class="hljs-attr">ports:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>
</code></pre>
<pre><code class="lang-bash">kubectl apply -f nginx-pod.yaml
</code></pre>
<p>You can list the pods using <code>kubectl get pods</code> command.</p>
<pre><code class="lang-bash">❯ kubectl get pods
NAME        READY   STATUS    RESTARTS      AGE
nginx-pod   1/1     Running   0             5s
</code></pre>
<h2 id="heading-lets-break-down-the-pod-manifest">Let's break down the Pod manifest</h2>
<p>When writing any object in Kubernetes, you need to include certain required fields: <code>apiVersion</code>, <code>kind</code>, <code>metadata</code>, and <code>spec</code>.</p>
<h3 id="heading-apiversion">apiVersion</h3>
<p>This field specifies the version of the Kubernetes API that your object adheres to, ensuring compatibility with your Kubernetes cluster (e.g., <code>v1</code>).</p>
<h3 id="heading-kind">kind</h3>
<p>This field defines the type of Kubernetes object being created. In our YAML file, it indicates that we are creating a Pod.</p>
<h3 id="heading-metadata">metadata</h3>
<p>This section provides essential information about the Pod:</p>
<ul>
<li><p><code>name</code>: This uniquely identifies the Pod within its namespace (e.g., <code>nginx-pod</code>).</p>
</li>
<li><p><code>namespace</code>: Assigns a specific namespace to the Pod for resource isolation.</p>
</li>
<li><p><code>labels</code>: These are key-value pairs used to organize and select resources (e.g., <code>app: nginx</code>).</p>
</li>
<li><p><code>annotations</code>: These key-value pairs offer additional details about the Pod, useful for documentation, debugging, or monitoring.</p>
</li>
<li><p><code>ownerReferences</code>: Specifies the controller managing the Pod, establishing a relationship hierarchy among Kubernetes resources.</p>
</li>
</ul>
<h3 id="heading-spec">spec</h3>
<p>The <code>spec</code> section defines the desired state of the Pod, including its containers and their configurations:</p>
<ul>
<li><p><code>containers</code>: This list defines each container within the Pod.</p>
<ul>
<li><p><code>name</code>: Identifies the container (e.g., <code>nginx-container</code>).</p>
</li>
<li><p><code>image</code>: Specifies the Docker image to use (e.g., <code>nginx:latest</code>).</p>
</li>
<li><p><code>ports</code>: Indicates which ports should be exposed by the container (e.g., port <code>80</code>).</p>
</li>
</ul>
</li>
</ul>
<p><strong>Additional Optional Fields</strong>: For more advanced setups, you can include additional fields within the <code>spec</code> section:</p>
<ul>
<li><p><code>resources</code>: Manages the Pod's resource requests and limits.</p>
</li>
<li><p><code>volumeMounts</code>: Specifies volumes to be mounted into the container's filesystem.</p>
</li>
<li><p><code>env</code>: Defines environment variables accessible to the container.</p>
</li>
<li><p><code>volumes</code>: Describes persistent storage volumes available to the Pod.</p>
</li>
</ul>
<h2 id="heading-static-pods">Static pods</h2>
<p>In Kubernetes, Static Pods offer a way to directly manage Pods on a node without the need for the Kubernetes control plane. Unlike regular Pods that are managed by the Kubernetes API server, Static Pods are managed directly by the Kubelet daemon on a specific node.</p>
<h4 id="heading-how-static-pods-work">How Static Pods Work</h4>
<p>Static Pods are defined by creating Pod manifest files on the node itself. These manifest files are usually located in a directory monitored by the Kubelet, such as <code>/etc/kubernetes/manifests</code>, or a directory specified in the Kubelet's configuration (<code>kubelet.conf</code>).</p>
<h4 id="heading-key-characteristics-of-static-pods">Key Characteristics of Static Pods</h4>
<ol>
<li><p><strong>Node-Specific Management</strong>: Each node runs its instance of the Kubelet, which monitors a designated directory for Pod manifests. When a manifest file is detected or updated, the Kubelet creates, updates, or deletes the corresponding Pod on that node.</p>
</li>
<li><p><strong>No Kubernetes API Interaction</strong>: Unlike regular Pods that are part of the Kubernetes API and etcd datastore, Static Pods are not managed via the API server. They do not appear in Kubernetes API responses and are not visible through tools like <code>kubectl</code>.</p>
</li>
<li><p><strong>Use Cases</strong>: Static Pods are useful in scenarios where Pods need to run directly on a node, independent of the Kubernetes control plane. This can include bootstrapping components required for Kubernetes itself, or running critical system daemons that must be available even if the control plane is offline.</p>
</li>
</ol>
<h4 id="heading-creating-static-pods">Creating Static Pods</h4>
<p>To create a Static Pod:</p>
<ul>
<li><p><strong>Create a Manifest File</strong>: Write a Pod manifest YAML file specifying the Pod's metadata and spec, similar to how you define regular Pods.</p>
</li>
<li><p><strong>Place in Watched Directory</strong>: Save the manifest file in the directory monitored by the Kubelet (<code>/etc/kubernetes/manifests</code> by default). This directory can be configured in the Kubelet configuration file by setting <code>staticPodPath</code> to the pod manifests path. Alternatively, it can also be passed to Kubelet through the <code>--pod-manifest-path</code> flag, but this flag is deprecated.</p>
</li>
<li><p><strong>If needed restart the kubelet</strong>:</p>
<pre><code class="lang-bash">  systemctl restart kubelet
</code></pre>
</li>
</ul>
<p>Static Pods in Kubernetes are managed directly by the Kubelet and are automatically restarted if they fail. The Kubelet ensures that each Static Pod's state aligns with its specified manifest file. Despite this direct management, Kubelet also attempts to create a mirror Pod on the API server for each Static Pod. This makes the static pod visible to the API server, however, the API server cannot control the pod.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Pods are the core units in Kubernetes, encapsulating containers with shared storage and network resources. They can run single or multiple containers, providing flexibility in application deployment. Understanding Pods' anatomy, lifecycle, and creation methods, including static Pods, is crucial for efficient and scalable application management in Kubernetes environments.</p>
<p><code>Pods in Kubernetes are inherently ephemeral and can be terminated at any time. Kubernetes uses controllers to effectively manage Pods, ensuring their desired state is maintained. ReplicationSet controllers ensure a specified number of Pod replicas are running. Other controllers like Deployments, StatefulSets, and DaemonSets cater to different use cases.</code></p>
<p><strong><em>Thank you for reading this blog; your interest is greatly appreciated, and I hope it helps you on your Kubernetes journey. In the next blog, we'll explore Kubernetes controllers that are used to manage Pods.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Creating a Kubernetes Cluster with Kubeadm and Containerd: A Comprehensive Step-by-Step Guide]]></title><description><![CDATA[Introduction
Kubeadm is a tool designed to simplify the process of creating Kubernetes clusters by providing kubeadm init and kubeadm join commands as best-practice "fast paths." - Kubernetes documentation
In this blog, we'll go through the step-by-s...]]></description><link>https://pratikjagrut.space/creating-a-kubernetes-cluster-with-kubeadm-and-containerd-a-comprehensive-step-by-step-guide</link><guid isPermaLink="true">https://pratikjagrut.space/creating-a-kubernetes-cluster-with-kubeadm-and-containerd-a-comprehensive-step-by-step-guide</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[containers]]></category><category><![CDATA[kubeadm]]></category><category><![CDATA[cluster]]></category><category><![CDATA[cka]]></category><category><![CDATA[ckad]]></category><category><![CDATA[k8s]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[step-by-step guide]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Sat, 22 Jun 2024 07:54:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1719153747285/23d49598-be16-4275-8a53-19052cd1bce8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Kubeadm is a tool designed to simplify the process of creating Kubernetes clusters by providing <code>kubeadm init</code> and <code>kubeadm join</code> commands as best-practice "fast paths." - Kubernetes documentation</p>
<p>In this blog, we'll go through the step-by-step process of installing a Kubernetes cluster using Kubeadm.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you begin, ensure you have the following:</p>
<ol>
<li><p>Ensure you have a compatible Linux host (e.g., Debian-based and Red Hat-based distributions). In this blog, we're using Ubuntu which is a Debian-based OS.</p>
</li>
<li><p>At least 2 GB of RAM and 2 CPUs per machine.</p>
</li>
<li><p>Full network connectivity between all machines in the cluster.</p>
</li>
<li><p>Unique hostname, MAC address, and product_uuid for every node.</p>
</li>
<li><p>Ensure all the required ports are open for the control plane and the worker nodes. You can refer to <a target="_blank" href="https://kubernetes.io/docs/reference/networking/ports-and-protocols">Ports and Protocols</a> or see the screenshot below.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718886897927/49b67a48-825f-4315-b336-71169fb5a644.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p><strong><em>Disable swap on all the nodes.</em></strong></p>
<pre><code class="lang-bash">sudo swapoff -a
<span class="hljs-comment"># disable swap on startup in /etc/fstab</span>
sudo sed -i <span class="hljs-string">'/ swap / s/^/#/'</span> /etc/fstab
</code></pre>
<h2 id="heading-setup-container-runtimecontainerd">Setup container runtime(Containerd)</h2>
<p>To run containers in Pods, Kubernetes uses a container runtime. By default, Kubernetes employs the <code>Container Runtime Interface (CRI)</code> to interact with your selected container runtime. Each node needs to have container runtime installed. In this blog, we'll use <code>containerd</code>.</p>
<p><strong><em>Run these instructions on all the nodes. I am using Ubuntu on all the nodes.</em></strong></p>
<ul>
<li><p><strong>Enable IPv4 packet forwarding:</strong></p>
<pre><code class="lang-bash">  <span class="hljs-comment"># sysctl params required by setup, params persist across reboots</span>
  cat &lt;&lt;EOF | sudo tee /etc/sysctl.d/k8s.conf
  net.ipv4.ip_forward = 1
  EOF

  <span class="hljs-comment"># Apply sysctl params without reboot</span>
  sudo sysctl --system
</code></pre>
<p>  Run <code>sudo sysctl net.ipv4.ip_forward</code> to verify that <code>net.ipv4.ip_forward</code> is set to 1</p>
</li>
<li><p><strong>Specify and load the following kernel module dependencies:</strong></p>
<pre><code class="lang-bash">  cat &lt;&lt;EOF | sudo tee /etc/modules-load.d/k8s.conf
  overlay
  br_netfilter
  EOF

  sudo modprobe overlay
  sudo modprobe br_netfilter
</code></pre>
</li>
<li><p><strong>Install containerd:</strong></p>
<p>  <strong><em>Add Docker's official GPG key:</em></strong></p>
<pre><code class="lang-bash">  sudo apt-get update
  sudo apt-get -y install ca-certificates curl
  sudo install -m 0755 -d /etc/apt/keyrings
  sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
  sudo chmod a+r /etc/apt/keyrings/docker.asc
</code></pre>
<p>  <strong><em>Add the repository to Apt sources:</em></strong></p>
<pre><code class="lang-bash">  <span class="hljs-built_in">echo</span> \
    <span class="hljs-string">"deb [arch=<span class="hljs-subst">$(dpkg --print-architecture)</span> signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
    <span class="hljs-subst">$(. /etc/os-release &amp;&amp; echo <span class="hljs-string">"<span class="hljs-variable">$VERSION_CODENAME</span>"</span>)</span> stable"</span> | \
    sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/null
</code></pre>
<p>  <strong><em>Install containerd</em></strong></p>
<pre><code class="lang-bash">  sudo apt-get update
  sudo apt-get -y install containerd.io
</code></pre>
<p>  For more details, refer to the <a target="_blank" href="https://github.com/containerd/containerd/blob/main/docs/getting-started.md#option-2-from-apt-get-or-dnf">Official installation documentation</a></p>
</li>
<li><p><strong>Configure systemd cgroup driver for containerd</strong></p>
<p>  First, we need to create a containerd configuration file at the location <code>/etc/containerd/config.toml</code></p>
<pre><code class="lang-bash">  sudo mkdir -p /etc/containerd
  sudo containerd config default | sudo tee /etc/containerd/config.toml
</code></pre>
<p>  Now, we enable the systemd cgroup driver for the CRI in <code>/etc/containerd/config.toml</code> at section <code>[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]</code> set <code>SystemCgroup = true</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718901406563/230cf196-74be-4fd7-b7df-c12b66a6c411.png" alt class="image--center mx-auto" /></p>
<p>  OR we can just run</p>
<pre><code class="lang-bash">  sudo sed -i <span class="hljs-string">"s/SystemdCgroup = false/SystemdCgroup = true/g"</span> <span class="hljs-string">"/etc/containerd/config.toml"</span>
</code></pre>
<p>  Restart containerd</p>
<pre><code class="lang-bash">  sudo systemctl restart containerd
</code></pre>
<p>  Containerd should be running, check the status using:</p>
<pre><code class="lang-bash">  sudo systemctl status containerd
</code></pre>
</li>
</ul>
<h2 id="heading-install-kubeadm-kubelet-and-kubectl">Install kubeadm, kubelet and kubectl</h2>
<p><strong><em>Run these commands on all nodes. These instructions are for Kubernetes v1.30.</em></strong></p>
<ul>
<li><p><strong>Install</strong><code>apt-transport-https, ca-certificates, curl, gpg</code><strong>packages</strong></p>
<pre><code class="lang-bash">  sudo apt-get update
  sudo apt-get install -y apt-transport-https ca-certificates curl gpg
</code></pre>
</li>
<li><p><strong>Download the public signing key for the Kubernetes package repositories</strong></p>
<pre><code class="lang-bash">  curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
</code></pre>
</li>
<li><p><strong>Add the</strong><code>apt</code><strong>repository for Kubernetes 1.30</strong></p>
<pre><code class="lang-bash">  <span class="hljs-built_in">echo</span> <span class="hljs-string">'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /'</span> | sudo tee /etc/apt/sources.list.d/kubernetes.list
</code></pre>
</li>
<li><p><strong>Install kubelet, kubeadm and kubectl</strong></p>
<pre><code class="lang-bash">  sudo apt-get update
  sudo apt-get install -y kubelet kubeadm kubectl
  sudo apt-mark hold kubelet kubeadm kubectl
</code></pre>
</li>
<li><p><strong>This is optional, Enable the kubelet service before running kubeadm</strong></p>
<pre><code class="lang-bash">  sudo systemctl <span class="hljs-built_in">enable</span> --now kubelet
</code></pre>
</li>
</ul>
<h2 id="heading-initialize-the-k8s-control-plane">Initialize the k8s control plane</h2>
<p><strong><em>Run these instructions only on the control plane node</em></strong></p>
<ul>
<li><p><strong><em>kubeadm init</em></strong></p>
<p>  To initialize the control plane, run the <code>kubeadm init</code> command. You also need to choose a pod network add-on and deploy a <code>Container Network Interface (CNI)</code> so that your Pods can communicate with each other. Cluster DNS (CoreDNS) will not start until a network is installed.</p>
<p>  We will use Calico CNI, so set the <code>--pod-network-cidr=192.168.0.0/16</code>.</p>
<pre><code class="lang-bash">  sudo kubeadm init --pod-network-cidr=192.168.0.0/16
</code></pre>
<p>  Now, at the end of the <code>kubeadm init</code> command, you'll see <code>kubeadm join</code> command</p>
<p>  <code>sudo kubeadm join &lt;control-plane-ip&gt;:&lt;control-plane-port&gt; --token &lt;token&gt; --discovery-token-ca-cert-hash &lt;hash&gt;</code> copy it and keep it safe.</p>
</li>
<li><p><strong>Run the following commands to set kubeconfig to access the cluster using kubectl</strong></p>
<pre><code class="lang-bash">  mkdir -p <span class="hljs-variable">$HOME</span>/.kube
  sudo cp -i /etc/kubernetes/admin.conf <span class="hljs-variable">$HOME</span>/.kube/config
  sudo chown $(id -u):$(id -g) <span class="hljs-variable">$HOME</span>/.kube/config
</code></pre>
<p>  Now, check the node using</p>
<pre><code class="lang-bash">  $ kubectl get nodes
  NAME             STATUS     ROLES           AGE    VERSION
  ip-zzz-zz-z-zz   NotReady   control-plane   114s   v1.30.2
</code></pre>
<p>  The node is in <code>NotReady</code> state because <code>message: 'container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized' reason: KubeletNotReady</code> . After setting up the CNI, the node should be in a Ready state.</p>
</li>
<li><p><strong>Set Up a Pod Network</strong></p>
<p>  We must deploy a Container Network Interface (CNI) based Pod network add-on so that Pods can communicate with each other.</p>
<p>  <strong><em>Install the calico operator on the cluster.</em></strong></p>
<pre><code class="lang-bash">  kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml
</code></pre>
<p>  <strong><em>Download the custom resources necessary to configure Calico.</em></strong></p>
<pre><code class="lang-bash">  kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/custom-resources.yaml
</code></pre>
<p>  <strong><em>Verify all the Calico pods are in running state.</em></strong></p>
<pre><code class="lang-bash">  $ kubectl get pods -n calico-system
  NAME                                       READY   STATUS    RESTARTS   AGE
  calico-kube-controllers-6f459db86d-mg657   1/1     Running   0          3m36s
  calico-node-ctc9q                          1/1     Running   0          3m36s
  calico-typha-774d5fbdb7-s7qsg              1/1     Running   0          3m36s
  csi-node-driver-bblm8                      2/2     Running   0          3m3
</code></pre>
<p>  <strong><em>Verify that the node is in a running state</em></strong></p>
<pre><code class="lang-bash">  $ kubectl get nodes
  NAME             STATUS   ROLES           AGE     VERSION
  ip-xxx-xx-x-xx   Ready    control-plane   2m46s   v1.30.2
</code></pre>
</li>
</ul>
<h2 id="heading-join-the-worker-nodes">Join the worker nodes</h2>
<p>Ensure <code>containerd</code>, <code>kubeadm</code>, <code>kubectl</code>, and <code>kubelet</code> are installed on all worker nodes, then run <code>sudo kubeadm join &lt;control-plane-ip&gt;:&lt;control-plane-port&gt; --token &lt;token&gt; --discovery-token-ca-cert-hash &lt;hash&gt;</code>, which you can find at the end of the <code>kubeadm init</code> command's output.</p>
<h3 id="heading-check-the-cluster-state">Check the cluster state</h3>
<p><strong><em>Run these commands on the control-plane node since the worker nodes do not have the kubeconfig file.</em></strong></p>
<ul>
<li><p><strong>Check if the worker nodes are joined to the cluster.</strong></p>
<pre><code class="lang-bash">  $ kubectl get nodes
  NAME               STATUS   ROLES           AGE    VERSION
  ip-xxx-xx-xx-xx    Ready    &lt;none&gt;          9m9s   v1.30.2
  ip-yyy-yy-yy-yy    Ready    &lt;none&gt;          23s    v1.30.2
  ip-zzz-zz-z-zz     Ready    control-plane   27m    v1.30.2
</code></pre>
<p>  To add a worker role to the worker node we can use <code>kubectl label node &lt;node-name&gt; node-role.kubernetes.io/worker=worker</code> command.</p>
<pre><code class="lang-bash">  $ kubectl get nodes
  NAME               STATUS   ROLES           AGE     VERSION
  ip-xxx-xx-xx-xx    Ready    worker          12m     v1.30.2
  ip-yyy-yy-yy-yy    Ready    worker          3m51s   v1.30.2
  ip-zzz-zz-z-zz     Ready    control-plane   31m     v1.30.2
</code></pre>
</li>
<li><p><strong>Check the workload running on the cluster</strong></p>
<pre><code class="lang-bash">  $ kubectl get pods -A
  NAMESPACE          NAME                                       READY   STATUS    RESTARTS   AGE
  calico-apiserver   calico-apiserver-6fcb65fbd5-n4wsn          1/1     Running   0          35m
  calico-apiserver   calico-apiserver-6fcb65fbd5-nnggl          1/1     Running   0          35m
  calico-system      calico-kube-controllers-6f459db86d-mg657   1/1     Running   0          35m
  calico-system      calico-node-ctc9q                          1/1     Running   0          35m
  calico-system      calico-node-dmgt2                          1/1     Running   0          18m
  calico-system      calico-node-nw4t5                          1/1     Running   0          9m49s
  calico-system      calico-typha-774d5fbdb7-s7qsg              1/1     Running   0          35m
  calico-system      calico-typha-774d5fbdb7-sxb5c              1/1     Running   0          9m39s
  calico-system      csi-node-driver-bblm8                      2/2     Running   0          35m
  calico-system      csi-node-driver-jk4sz                      2/2     Running   0          18m
  calico-system      csi-node-driver-tbrrj                      2/2     Running   0          9m49s
  kube-system        coredns-7db6d8ff4d-5f7s5                   1/1     Running   0          37m
  kube-system        coredns-7db6d8ff4d-qj9r8                   1/1     Running   0          37m
  kube-system        etcd-ip-zzz-zz-z-zz                        1/1     Running   0          37m
  kube-system        kube-apiserver-ip-zzz-zz-z-zz              1/1     Running   0          37m
  kube-system        kube-controller-manager-ip-zzz-zz-z-zz     1/1     Running   0          37m
  kube-system        kube-proxy-dq8k4                           1/1     Running   0          9m49s
  kube-system        kube-proxy-t2sw9                           1/1     Running   0          18m
  kube-system        kube-proxy-xd6nn                           1/1     Running   0          37m
  kube-system        kube-scheduler-ip-zzz-zz-z-zz              1/1     Running   0          37m
  tigera-operator    tigera-operator-76ff79f7fd-jj4kf           1/1     Running   0          35m
</code></pre>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Setting up a Kubernetes cluster with Kubeadm involves a clear and structured process. You can create a functional cluster by meeting all prerequisites, configuring the container runtime, and installing Kubernetes components. Using Calico for networking ensures seamless pod communication. With the control plane and worker nodes properly configured and joined, you can efficiently manage and deploy workloads across your Kubernetes cluster.</p>
<p><strong><em>Thank you for reading this blog; your interest is greatly appreciated, and I hope it helps you on your Kubernetes journey; in the next article, we'll explore running workloads in the Kubernetes cluster.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Introduction to Kubernetes]]></title><description><![CDATA[What is Kubernetes?
Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. Kubernetes se...]]></description><link>https://pratikjagrut.space/introduction-to-kubernetes</link><guid isPermaLink="true">https://pratikjagrut.space/introduction-to-kubernetes</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[containers]]></category><category><![CDATA[container orchestration]]></category><category><![CDATA[k8s]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Wed, 19 Jun 2024 17:08:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718824969406/3817189f-91b4-4ada-b6e2-9edf4c4cac31.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-kubernetes">What is Kubernetes?</h2>
<p><code>Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. Kubernetes services, support, and tools are widely available.</code> - <em>From Kubernetes Docs</em></p>
<p>In simpler terms, Kubernetes, also known as an orchestrator, is an open-source platform that automates the management of containers. Originally developed by <code>Google</code> as an internal container management project named <code>Borg</code>, Kubernetes was made open-source on <code>June 7, 2014</code>. In <code>July 2015</code>, it was donated to the <code>Cloud Native Computing Foundation (CNCF)</code>.</p>
<p>Kubernetes means <code>helmsman</code> or <code>pilot</code> in Greek, reflecting its role in guiding containerized applications. It is also known as <code>k8s</code>, a shorthand that represents the <code>8 letters between the 'k' and the 's'</code> .</p>
<h2 id="heading-key-features">Key Features</h2>
<p>Kubernetes offers a robust set of features, including:</p>
<ul>
<li><p><strong>Automatic Bin Packing:</strong> Schedules containers automatically based on resource needs and constraints, ensuring efficient utilization without compromising availability.</p>
</li>
<li><p><strong>Self-Healing:</strong> Replaces and reschedules containers from failed nodes, restarts unresponsive containers, and prevents traffic from being routed to them.</p>
</li>
<li><p><strong>Horizontal Scaling:</strong> Scales applications manually or automatically based on CPU or custom metrics utilization.</p>
</li>
<li><p><strong>Service Discovery and Load Balancing:</strong> Assigns IP addresses to containers and provides a single DNS name for a set of containers to facilitate load balancing.</p>
</li>
<li><p><strong>Automated Rollouts and Rollbacks:</strong> Manages seamless rollouts and rollbacks of application updates and configuration changes, continuously monitoring application health to prevent downtime.</p>
</li>
<li><p><strong>Secret and Config Management:</strong> Manages secrets and configuration details separately from container images, avoiding the need to rebuild images.</p>
</li>
<li><p><strong>Storage Orchestration:</strong> Automatically mounts storage solutions to containers from local storage, cloud providers, or network storage systems.</p>
</li>
<li><p><strong>Batch Execution:</strong> Supports batch execution and long-running jobs, and replaces failed containers as needed.</p>
</li>
<li><p><strong>Role-Based Access Control (RBAC):</strong> Regulates access to cluster resources based on user roles within an enterprise.</p>
</li>
<li><p><strong>Extensibility:</strong> Extends functionality through Custom Resource Definitions (CRDs), operators, custom APIs, and more.</p>
</li>
</ul>
<p>With its extensive array of capabilities, Kubernetes simplifies the management of containerized applications, ensuring optimal efficiency and performance, while also providing scalability, resilience, and flexibility for diverse workloads.</p>
<h2 id="heading-cluster-architecture">Cluster Architecture</h2>
<p>Kubernetes cluster has a straightforward yet elegant and efficient architecture, consisting of at least one <code>master node</code>, also known as a <code>control-plane node</code>, and at least one <code>worker node</code>. The diagram below illustrates the cluster architecture.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718725391854/d7b025b8-21df-44a7-9656-441eb93c0c33.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-control-plane-node">Control-plane node</h3>
<p>The control plane is responsible for maintaining the overall state of the cluster. The control plane includes components like the API server, scheduler, controller manager, and etcd, which coordinate and manage the cluster operations.</p>
<p><strong>kube-api-server</strong></p>
<p>The Kubernetes API server serves as the core of the control plane. It exposes an HTTP API through which users, external components, and cluster components securely interact to manage the state of Kubernetes objects. It validates incoming requests before storing them and supports the incorporation of custom API servers to expand its functionality. Highly configurable, it accommodates diverse configurations and extensions to suit specific cluster requirements.</p>
<p><strong>Scheduler</strong></p>
<p>The Kubernetes scheduler watches for newly created pods without assigned nodes and selects suitable nodes for them. It retrieves resource usage data for each worker node from etcd via the API server. Additionally, it incorporates scheduling requirements specified in the pod's configuration, such as the preference to run on nodes labelled with specific attributes like "disk==ssd".</p>
<p>So basically, the scheduler is responsible for assigning a node to a pod based on available resources and scheduling constraints.</p>
<p><strong>kube-controller-manager</strong></p>
<p>The kube-controller-manager is a collection of different Kubernetes controllers, running as a single binary. It ensures that the <code>actual state of objects matches their desired state</code>. Each controller watches over its objects, maintains their state, and plays a specific role in maintaining the health and desired configuration of the cluster. Key controllers within kube-controller-manager include the <code>ReplicaSet controller, Deployment controller, Namespace controller, ServiceAccount controller, Endpoint controller, and Persistent Volume controller</code>.</p>
<p><strong>cloud-controller-manager</strong></p>
<p>The cloud-controller-manager includes the <code>Node controller, Route controller, Service controller, and Volume controller</code>. These controllers are responsible for interfacing with the cloud infrastructure to manage nodes, storage volumes, load balancing, and routing. They ensure seamless integration and management of cloud resources within the Kubernetes cluster.</p>
<p><strong>ETCD</strong></p>
<p>ETCD is a distributed key-value store used to persist the state of a Kubernetes cluster. New data is always appended, never replaced, and obsolete data is compacted periodically to reduce the data store size. Only the Kubernetes API server can communicate directly with ETCD to ensure consistency and security. The ETCD CLI management tool provides capabilities for backup, snapshot, and restore.</p>
<h3 id="heading-worker-node">Worker node</h3>
<p>A worker node in Kubernetes executes application workloads by hosting and managing containers, providing essential computational resources within the cluster. It consists of components such as the <code>Kubelet</code>, <code>kube-proxy</code>, and a <code>container runtime interface(CRI)</code> like <code>Docker</code> or <code>containerd</code>.</p>
<p><strong>Kubelet</strong></p>
<p>The kubelet operates as an agent on each node within the Kubernetes cluster, maintaining communication with the control plane components. It receives pod definitions from the API server and coordinates with the container runtime to instantiate and manage containers associated with those pods. The kubelet also monitors the health and lifecycle of containers and manages resources as per pod specifications.</p>
<p><strong>kube-proxy</strong></p>
<p>The kube-proxy is a network agent running on each node in the Kubernetes cluster. It dynamically updates and maintains the network rules on the node to facilitate communication between pods and external traffic. It abstracts the complexities of pod networking by managing services and routing connections to the appropriate pods based on IP address and port number.</p>
<p><strong>Container Runtime</strong></p>
<p>In Kubernetes, a container runtime is essential for each node to handle the lifecycle of containers. Some of the known container runtimes are Docker, CRI-O, containerd, and rkt. These runtimes interface with Kubernetes using the Container Runtime Interface (CRI), ensuring that containers are created, managed, and terminated as needed within the cluster.</p>
<p><strong>Pod</strong></p>
<p>In Kubernetes, you cannot directly run containers as you would with Docker. Instead, containers are grouped into units called pods. A pod can host multiple containers and is the smallest deployable object in Kubernetes.</p>
<h2 id="heading-how-does-all-of-this-come-together">How does all of this come together?</h2>
<p>Let's see this with an example of pod creation:</p>
<p>First, define the pod by creating a YAML or JSON file that specifies its configuration, including <code>container images, resource requirements, environment variables, storage volumes etc</code>. This file acts as the pod's blueprint.</p>
<p>Once you have the pod definition file ready, you submit it to the Kubernetes API server using the <code>kubectl</code> command-line tool. For instance, you can apply the configuration with a command like <code>kubectl apply -f pod-definition.yaml</code>. Alternatively, you can create the pod directly with a command such as <code>kubectl run my-pod --image=my-image</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718814000515/8a2a5de7-0ff0-4ed2-be16-be6b1227b1e1.png" alt class="image--center mx-auto" /></p>
<p>The Kubernetes API server receives and validates the pod creation request, ensuring it meets all criteria. Once validated, it stores the pod definition in etcd, the cluster's key-value store.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718813953953/38ddc973-bad1-4256-a487-e776d3258157.png" alt class="image--center mx-auto" /></p>
<p>The Kubernetes scheduler watches for newly created <code>pods without assigned nodes</code>. It interacts with the API server to get the pod configuration, evaluates the resource requirements and constraints, and then selects a suitable worker node for the pod, updating the pod configuration with the <code>nodeName</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718813898885/ebea2757-0d78-4f8d-a46f-223697cbe6eb.png" alt class="image--center mx-auto" /></p>
<p>On the assigned node, the kubelet receives the pod definition from the API server. <code>It manages pods and their containers, retrieves container images from a registry if needed, and uses the container runtime (like Docker or containerd) to create and start containers</code> as specified and <code>also set up storage as required</code>. It monitors container health and can restart them based on defined policies. Meanwhile, <code>kube-proxy configures networking rules for pod communication</code>. When all containers are running and ready, the pod can accept traffic, showcasing Kubernetes' orchestration in maintaining application states.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1718815102888/d14984af-5e66-46aa-b961-0ef5b23da3bf.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Kubernetes is a robust platform for managing containerized applications, offering features that simplify deployment, scaling, and maintenance. This article covered its origins, core functionalities, and architecture. Leveraging Kubernetes enhances efficiency, resilience, and flexibility, making it essential for modern cloud-native environments.</p>
<p><strong><em>Thank you for reading this blog; your interest is greatly appreciated, and I hope it helps you on your Kubernetes journey; in the next article, we'll explore how to install Kubernetes using the Kubeadm tool.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Introduction to Container Orchestration]]></title><description><![CDATA[Introduction
Containerization has revolutionized how we develop and deploy software, streamlining processes and enhancing scalability. It all began modestly in 1979 with the introduction of chroot, a Unix feature that allowed applications to operate ...]]></description><link>https://pratikjagrut.space/introduction-to-container-orchestration</link><guid isPermaLink="true">https://pratikjagrut.space/introduction-to-container-orchestration</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[containers]]></category><category><![CDATA[container orchestration]]></category><category><![CDATA[containerization]]></category><category><![CDATA[k8s]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Sat, 15 Jun 2024 10:48:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718435827233/cfacd6d8-7827-4139-af24-5c00223f6135.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Containerization has revolutionized how we develop and deploy software, streamlining processes and enhancing scalability. It all began modestly in <code>1979</code> with the introduction of <code>chroot</code>, a Unix feature that allowed applications to operate within a confined directory subset. This breakthrough laid the groundwork for application isolation, a crucial concept for modern containerization.</p>
<p>Building upon chroot, FreeBSD's introduction of <code>jails</code> in 2000 marked a significant advancement. Jails provided a more robust form of isolation within a FreeBSD environment, enabling multiple applications to run securely on the same host without interference. This development was pivotal in demonstrating the practicality of isolating software environments for enhanced security and efficiency.</p>
<p>Following FreeBSD, <code>Solaris Containers (2004),</code> also known as <code>Zones</code> refined containerization by introducing sophisticated resource management capabilities. Zones allowed administrators to allocate specific CPU, memory, and storage resources to each container, optimizing hardware utilization and paving the way for efficient data centre management.</p>
<p>Google's <code>control group(cgroup)</code>, integrated into the Linux kernel in <code>2007</code>, brought fine-grained resource control to Linux-based containers. This innovation enabled administrators to manage and isolate resource usage among groups of processes, enhancing predictability and performance in containerized environments.</p>
<p>The culmination of these advancements led to the creation of <code>Linux Containers (LXC) in 2008</code>, which provided a user-friendly interface for leveraging Linux kernel features like <code>cgroups</code> and <code>namespaces</code>. LXC enabled the creation and management of lightweight, isolated Linux environments, marking a significant milestone towards the widespread adoption of container technology.</p>
<p><code>In 2013, Docker</code> revolutionized containerization with its user-friendly platform for creating, deploying, and managing containers. Initially built upon LXC, Docker later introduced its <code>container runtime and libcontainer</code>, which l<code>everaged Linux namespaces, control groups, and other kernel features</code>. Docker's standardized container format and tooling simplified application packaging and deployment, accelerating the adoption of containers in both development and production environments.</p>
<p>Around the same time, the technological landscape experienced a major shift in software architecture. It moved from monolithic applications, where all modules run on a single machine and are tightly coupled, to a more decentralized and scalable model known as microservices architecture. In the 2000s, the rise of microservices architecture and the adoption of cloud computing rapidly accelerated the use of containerization. However, efficiently managing and orchestrating these containers remains a significant challenge.</p>
<h2 id="heading-challenges-in-container-management"><strong>Challenges in Container Management</strong></h2>
<p>Efficiently managing and orchestrating these containers at scale remains a formidable task, presenting challenges such as:</p>
<ul>
<li><p><strong>Deployment</strong>: Deploying numerous containers across diverse environments requires meticulous handling of versions, dependencies, and configurations to ensure consistency and reliability.</p>
</li>
<li><p><strong>Scaling</strong>: Applications must scale dynamically to meet varying demands, necessitating automated mechanisms that optimize resource usage without manual intervention.</p>
</li>
<li><p><strong>Networking</strong>: Effective networking is essential for seamless service discovery, load balancing, and secure communication among containers, demanding robust management policies.</p>
</li>
<li><p><strong>Resource Management</strong>: Efficient allocation of CPU, memory, and storage resources is critical to prevent performance bottlenecks and control operational costs effectively.</p>
</li>
<li><p><strong>Security</strong>: Ensuring container security requires implementing strict access controls, secure configurations, and isolation strategies to mitigate risks of breaches.</p>
</li>
<li><p><strong>High Availability</strong>: Maintaining application availability involves proactive management of container failures, load balancing, and resilient failover strategies to minimize downtime.</p>
</li>
</ul>
<p>Addressing these challenges is crucial for leveraging the full potential of containerization, enabling agility, scalability, and efficiency in software development and deployment.</p>
<h2 id="heading-container-orchestration">Container Orchestration</h2>
<p>While containerization has revolutionized software deployment, efficiently managing and scaling containerized applications across complex environments remains a daunting task. Container orchestration addresses these challenges by automating deployment, scaling, and management processes, ensuring applications run seamlessly from development through to production.</p>
<p><strong>Container Orchestrators</strong></p>
<p>Container orchestrators are tools that group systems together to form clusters where container deployment and management are automated at scale while meeting the production requirements.</p>
<p>They provide essential functionalities such as:</p>
<ul>
<li><p><strong>Automated Deployment</strong>: Simplifying the deployment process with declarative configurations and automated rollouts.</p>
</li>
<li><p><strong>Scalability</strong>: Enabling horizontal scaling of applications based on resource demands, ensuring performance and efficiency.</p>
</li>
<li><p><strong>Networking Automation</strong>: Facilitating efficient networking by managing service discovery, load balancing, and network security policies.</p>
</li>
<li><p><strong>Resource Optimization</strong>: Optimizing resource allocation and utilization to enhance performance and reduce operational costs.</p>
</li>
<li><p><strong>Security Enhancements</strong>: Implementing security best practices, including isolation mechanisms, encryption, and access controls.</p>
</li>
<li><p><strong>High Availability Strategies</strong>: Ensuring continuous application availability through automated failover, load distribution, and recovery mechanisms.</p>
</li>
</ul>
<p>Popular Container Orchestrators are:</p>
<ol>
<li><p><strong>Kubernetes</strong>:</p>
<ul>
<li><p>Developed by Google and is now maintained by the Cloud Native Computing Foundation (CNCF).</p>
</li>
<li><p>Features: Automatic bin packing, self-healing, horizontal scaling, service discovery, load balancing, and automated rollouts and rollbacks.</p>
</li>
</ul>
</li>
<li><p><strong>Docker Swarm</strong>:</p>
<ul>
<li><p>Native clustering and orchestration solution for Docker containers.</p>
</li>
<li><p>Features: Easy setup, Docker CLI compatibility, service discovery, load balancing, scaling, and rolling updates.</p>
</li>
</ul>
</li>
<li><p><strong>Apache Mesos</strong>:</p>
<ul>
<li><p>An open-source project that abstracts CPU, memory, storage, and other compute resources away from machines.</p>
</li>
<li><p>Features: Highly scalable, supports multiple frameworks, resource isolation, fault-tolerance, and elasticity.</p>
</li>
</ul>
</li>
<li><p><strong>Nomad</strong>:</p>
<ul>
<li><p>Developed by HashiCorp, it is a flexible and simple workload orchestrator.</p>
</li>
<li><p>Features: Multi-region, multi-cloud deployment, integrates with Consul for service discovery and Vault for secrets management, easy to use, and supports multiple workloads (Docker, non-containerized, Windows, etc.).</p>
</li>
</ul>
</li>
<li><p><strong>OpenShift</strong>:</p>
<ul>
<li><p>Developed by Red Hat, built on top of Kubernetes with additional features.</p>
</li>
<li><p>Features: Developer and operational tools, automated installation, upgrade management, monitoring, logging, and security policies.</p>
</li>
</ul>
</li>
<li><p><strong>Rancher</strong>:</p>
<ul>
<li><p>An open-source platform for managing Kubernetes at scale.</p>
</li>
<li><p>Features: Multi-cluster management, integrated monitoring and logging, centralized RBAC, and supports any Kubernetes distribution.</p>
</li>
</ul>
</li>
<li><p><strong>Amazon Elastic Kubernetes Service (EKS)</strong>:</p>
<ul>
<li><p>Managed Kubernetes service by Amazon Web Services.</p>
</li>
<li><p>Features: Fully managed, integrated with AWS services, auto-scaling, security, and compliance.</p>
</li>
</ul>
</li>
<li><p><strong>Google Kubernetes Engine (GKE)</strong>:</p>
<ul>
<li><p>Managed Kubernetes service by Google Cloud.</p>
</li>
<li><p>Features: Fully managed, integrated with Google Cloud services, auto-scaling, security, and compliance.</p>
</li>
</ul>
</li>
<li><p><strong>Azure Kubernetes Service (AKS)</strong>:</p>
<ul>
<li><p>Managed Kubernetes service by Microsoft Azure.</p>
</li>
<li><p>Features: Fully managed, integrated with Azure services, auto-scaling, security, and compliance.</p>
</li>
</ul>
</li>
<li><p><strong>IBM Cloud Kubernetes Service</strong>:</p>
<ul>
<li><p>Managed Kubernetes service by IBM Cloud.</p>
</li>
<li><p>Features: Fully managed, integrated with IBM Cloud services, auto-scaling, security, and compliance.</p>
</li>
</ul>
</li>
<li><p><strong>Alibaba Cloud Container Service for Kubernetes (ACK)</strong>:</p>
<ul>
<li><p>Managed Kubernetes service by Alibaba Cloud.</p>
</li>
<li><p>Features: Fully managed, integrated with Alibaba Cloud services, auto-scaling, security, and compliance.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In conclusion, containerization has revolutionized software development and deployment, offering scalability, efficiency, and agility crucial in today's dynamic landscape. As we've explored the evolution from chroot to Docker and the challenges of managing containerized environments, it's clear that container orchestration is pivotal.</p>
<p><strong><em>Thank you for reading this blog; your interest is greatly appreciated, and I hope it helps you on your Kubernetes journey; in the next blog, we'll explore Kubernetes, covering its features, architecture and core components.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Go GraphQL Go!!!]]></title><description><![CDATA[Have you ever wondered how computers and applications communicate with each other to fetch information? Well, they use something called an API, which stands for Application Programming Interface. APIs act as a bridge that allows different software sy...]]></description><link>https://pratikjagrut.space/go-graphql-go</link><guid isPermaLink="true">https://pratikjagrut.space/go-graphql-go</guid><category><![CDATA[Go Language]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[entity framework]]></category><category><![CDATA[ent]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Wed, 16 Aug 2023 08:16:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692173308546/1e5cbd65-ed7e-4e02-9cea-d876d18dc442.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever wondered how computers and applications communicate with each other to fetch information? Well, they use something called an API, which stands for Application Programming Interface. APIs act as a bridge that allows different software systems to talk to each other and exchange data.</p>
<p>In the early days of the Internet, building APIs was challenging. Developers had to design them in a way that made sense for everyone using them. It was like trying to order a drink from a bartender who had a complex menu with too many options. You would often end up getting more information than you needed or not enough, like ordering a simple orange juice and receiving the entire fruit basket! This caused frustration and wasted time for developers who had to sift through unnecessary data or make multiple requests to get what they wanted. Imagine having to ask the bartender for a drink, but instead of a simple order, you received an entire catalogue of beverages! To make matters worse, traditional APIs, known as REST APIs, relied on a large number of endpoints. These endpoints acted as specific paths to access different parts of the data. It was like having a maze with countless doors to navigate through. But then, something game-changing happened. Facebook introduced GraphQL, a revolutionary approach to building APIs in 2012 that turned the tables completely. With GraphQL, developers finally said goodbye to the headaches of over-fetching and under-fetching data. Fast forward to 2015, Facebook open-sourced GraphQL and in 2018 it donated GraphQL to the Linux Foundation.</p>
<p>GraphQL is a query language for API or some may say it is a new standard for developing APIs.</p>
<p>In this blog, we're going to explore how GraphQL tackles the challenges faced by traditional REST APIs. We'll also embark on a hands-on journey of building a GraphQL server in Go and to make our development process even more exciting and efficient, we'll leverage the power of Ent, an amazing entity library designed specifically for Go.</p>
<h3 id="heading-graphql-the-saviour">GraphQL the saviour</h3>
<p>In the introduction, we mentioned issues of RESTful APIs. Let’s try to understand them and look into how GraphQL solves them.</p>
<p>Imagine you're at a library, and you want to gather information about different books. You go to the librarian and request details about a book's title, author, and publication date. The librarian gives you the title, but when you ask for the author's email or address or other books published by the same author, they tell you to go to a different librarian. To get all the information you need, you have to keep bouncing between different librarians. This is called <strong><em>under-fetching</em></strong> of data.</p>
<p>In the world of software and applications, a similar situation occurs when fetching data from servers.</p>
<p>Let's consider a scenario where you're using a book catalogue API to fetch information about different books. If you want to retrieve the name of the author for a specific book, you would typically need to make multiple API calls to different endpoints.</p>
<p>For instance, the if want to fetch the author-related details from the database then we might first hit on /<strong><em>books/:$id</em></strong>. Here, in the backend we might need to make two queries, the first query will fetch the book with a particular id or just the author id from the book table and then we'll have to make a second query to the author table with the author id and fetch the record, assuming author-related information is stored in a separate table.</p>
<pre><code class="lang-bash">Request 1: GET /books/1
Response 1:
<span class="hljs-string">"book"</span>:
   {
     <span class="hljs-string">"id"</span>: 1,
     <span class="hljs-string">"title"</span>: <span class="hljs-string">"The Ink Black Heart"</span>,
     <span class="hljs-string">"genre"</span>: <span class="hljs-string">"Mystery"</span>,
     <span class="hljs-string">"publicationDate"</span>: <span class="hljs-string">"30 August 2022"</span>,
     <span class="hljs-string">"isbn"</span>: <span class="hljs-string">"9780316413138"</span>
     <span class="hljs-string">"author_id"</span>: <span class="hljs-string">"123"</span>
   }

Request 2: GET /authors/123
Response 2:
<span class="hljs-string">"author"</span>:
  {
      <span class="hljs-string">"id"</span>: 123,
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"J. K. Rowling"</span>
  }
</code></pre>
<p>As you can see, the server has to make multiple calls to different endpoints to fulfil this request, resulting in what we call <strong><em>under-fetching</em></strong> of data. It means that the API fails to retrieve all the required data in a single call, leading to additional requests and unnecessary processing.</p>
<p>On the other hand, there's the issue of <strong><em>over-fetching</em></strong> data.</p>
<p>Imagine you're at a magical restaurant where you can order any food or drink you desire. You walk up to the bartender and say, "I'd like a drink, please." The bartender nods, disappears for a moment, and returns with a tray filled with every drink imaginable: water, soda, juice, cocktails, and even a bowl of soup! You only wanted a simple glass of lemonade, but now you're overwhelmed with choices. This is called <strong><em>over-fetching</em></strong> of data.</p>
<p>Let's say you only need the name of the author for a particular book. However, the server, following a traditional RESTful approach, fetches and sends all the available information about the author, such as their <strong><em>ID, phone number, email, and address</em></strong>. This extra data retrieval and processing are considered over-fetching, as it includes more information than necessary.</p>
<p>These types of data requests can strain system resources, resulting in high traffic and reduced performance. The continuous accumulation of such inefficient requests can degrade the system's overall performance and scalability over time.</p>
<p>The GraphQL solves above issues with only one API call.</p>
<pre><code class="lang-graphql"><span class="hljs-symbol">Request:</span> Get /graphql
<span class="hljs-symbol">Body:</span>
{
  <span class="hljs-string">"query"</span>: <span class="hljs-string">"
    query {
      books {
        title
        genre
        author {
          name
        }
      }
    }
  "</span>
}

<span class="hljs-symbol">Response:</span>
{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"books"</span>: [
      {
        <span class="hljs-string">"title"</span>: <span class="hljs-string">"The Ink Black Heart"</span>,
        <span class="hljs-string">"genre"</span>: <span class="hljs-string">"Mystery"</span>,
        <span class="hljs-string">"author"</span>: {
          <span class="hljs-string">"name"</span>: <span class="hljs-string">"J. K. Rowling"</span>
        }
      },
      <span class="hljs-punctuation">...
</span>    ]
  }
}
</code></pre>
<p>As you can see, the GraphQL query precisely defines the fields needed: <strong>book title, genre, and the nested author's name</strong>. The response contains only the requested data, eliminating under-fetching and over-fetching issues. This approach reduces network overhead, improves performance, and enhances the overall developer and user experience.</p>
<p>In the case of smaller companies with a limited user base, the challenges of over-fetching and under-fetching data may not pose significant problems. However, for behemoths like Facebook, which handles an enormous amount of data and millions of requests per second, these issues become critical. When serving user requests, Facebook often needs to make multiple REST calls to fetch the precise data required. The multiplication effect of even a few million extra requests can overload the servers with processing overhead, leading to high traffic and reduced performance.</p>
<h3 id="heading-query-and-mutation">Query and Mutation</h3>
<p>To fully understand GraphQL we need to understand the Query and Mutation first.</p>
<p><strong>Queries:</strong></p>
<p>In GraphQL, queries are used to retrieve data from the server. They allow you to specify the exact data you need and the shape of the response. You define a query by specifying the fields you want to fetch and their relationships. The server processes the query and returns the requested data in a structured format, typically JSON.</p>
<p>For example, a query in GraphQL for retrieving book information may look like this:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">query</span> {
  book(<span class="hljs-symbol">id:</span> <span class="hljs-number">123</span>) {
    title
    genre
    author {
      name
    }
  }
}
</code></pre>
<p>This query asks the server to fetch the title and genre of a book with the ID 123, along with the name of its author. The response will only contain the requested fields.</p>
<p><strong>Mutations:</strong></p>
<p>Mutations in GraphQL are used to modify or create data on the server. They allow you to perform operations such as creating new records, updating existing ones, or deleting data. Mutations are analogous to the POST, PUT, or DELETE methods in RESTful APIs.</p>
<p>For example, a mutation in GraphQL for creating a book and its author may look like this:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">mutation</span> {
  createBook(<span class="hljs-symbol">title:</span> <span class="hljs-string">"The Ink Black Heart"</span>, <span class="hljs-symbol">genre:</span> <span class="hljs-string">"Mystery"</span>, <span class="hljs-symbol">author:</span> <span class="hljs-string">"J. K. Rowling"</span>) {
    id
    title
    genre
    author {
      id
      name
    }
  }
}
</code></pre>
<p>This mutation creates a new book with the title "The Ink Black Heart", genre "Mystery", and assigns it to the author "J. K. Rowling". The response will contain the ID, title, genre, and the ID and name of the author of the created book.</p>
<p>By using queries and mutations, GraphQL provides a flexible and efficient way to retrieve and modify data from a server. Clients can request precisely what they need, and mutations enable them to modify the data while maintaining a clear and consistent API contract.</p>
<p>For more information about GraphQL and what it can do or maybe on writing complex queries or mutations, you can visit the <a target="_blank" href="https://graphql.org/code/">official documentation</a>.</p>
<h2 id="heading-lets-code">Let's Code</h2>
<p>In this blog, we’ll develop a very minimal graphql server for the book catalogue application where we’ll be able to create book and author entities in the database and fetch them. The source code for this project is available at <a target="_blank" href="https://github.com/pratikjagrut/book-catalog.git">pratikjagrut/book-catalog</a>.</p>
<h3 id="heading-prerequisite"><strong>Prerequisite</strong></h3>
<p><a target="_blank" href="https://go.dev/doc/install">Go</a></p>
<h3 id="heading-setting-up-ent"><strong>Setting up Ent</strong></h3>
<p>Ent is an open-source entity framework designed specifically for Go. Think of it as a tool that helps us work with databases in an easier and more organized way. Ent has gained popularity in the Go community for its unique features and benefits.</p>
<p>Originally developed at Facebook, Ent was created to address the challenges of managing applications with large and complex data models. It was successfully used within Facebook for a year before being open-sourced in 2019. Since then, Ent has grown and even joined the Linux Foundation in 2021.</p>
<p>For detailed information on Ent see the <a target="_blank" href="https://entgo.io/">docs</a>.</p>
<p>After installing prerequisite dependencies, create a directory for the project and initialize a Go module:</p>
<pre><code class="lang-bash">mkdir book-catalog
<span class="hljs-built_in">cd</span> book-catalog
go mod init github.com/pratikjagrut/book-catalog
</code></pre>
<p><strong>Installation</strong></p>
<p>Run the following Go commands to install Ent, and tell it to initialize the project structure along with a <strong>Book</strong> schema.</p>
<pre><code class="lang-bash">go get -d entgo.io/ent/cmd/ent
go run -mod=mod entgo.io/ent/cmd/ent new Book
go run -mod=mod entgo.io/ent/cmd/ent new Author
</code></pre>
<p>After installing Ent and running <strong>ent new</strong>, your project directory should look like this:</p>
<pre><code class="lang-bash">➜  book-catalog git:(main) ✗ tree .
.
├── ent
│   ├── generate.go
│   └── schema
│       ├── author.go
│       └── book.go
├── go.mod
└── go.sum

2 directories, 5 files
</code></pre>
<p><strong>Code Generation</strong></p>
<p>When you run the ent new command it generates a schema file for you at <strong><em>ent/schema/book.go</em></strong></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> schema

<span class="hljs-keyword">import</span> <span class="hljs-string">"entgo.io/ent"</span>

<span class="hljs-comment">// Book holds the schema definition for the Book entity.</span>
<span class="hljs-keyword">type</span> Book <span class="hljs-keyword">struct</span> {
   ent.Schema
}

<span class="hljs-comment">// Fields of the Book.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Book)</span> <span class="hljs-title">Fields</span><span class="hljs-params">()</span> []<span class="hljs-title">ent</span>.<span class="hljs-title">Field</span></span> {
   <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
}

<span class="hljs-comment">// Edges of the Book.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Book)</span> <span class="hljs-title">Edges</span><span class="hljs-params">()</span> []<span class="hljs-title">ent</span>.<span class="hljs-title">Edge</span></span> {
   <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
}
</code></pre>
<p>As you can see, initially, the schema has no fields or edges defined. Let's run the command for generating assets to interact with the Book and Author entity:</p>
<pre><code class="lang-bash">go generate ./ent
</code></pre>
<p>When we run the command <strong><em>go generate ./ent</em></strong>, it triggers Ent's automatic code generation tool. This tool takes the schemas we define in the schema package and generates the corresponding Go code. This generated code will enable us to interact with the database.</p>
<p>After running the code generation, you'll find a file named <strong><em>client.go</em></strong> under the <strong><em>./ent</em></strong> directory. This file contains client code that allows us to perform queries and mutations on the entities. It serves as our gateway to interact with the database.</p>
<p>Let's create a test to use this. We'll use <a target="_blank" href="https://github.com/mattn/go-sqlite3">SQLite</a> in this test case for testing Ent.</p>
<pre><code class="lang-bash">go get github.com/mattn/go-sqlite3
go get github.com/stretchr/testify/assert
touch ent/book-catalog_test.go
</code></pre>
<p>You can add the following code to your <strong><em>book-catalog_test.go</em></strong> file. This code creates an instance of <strong><em>ent.Client</em></strong> automatically generates all the necessary schema resources in the database, including tables and columns.</p>
<p>At this stage, the test only establishes a connection and creates a schema without any fields or edges. However, we will update and expand this test as we progress through the blog.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> ent

<span class="hljs-keyword">import</span> (
   <span class="hljs-string">"context"</span>
   <span class="hljs-string">"testing"</span>

   <span class="hljs-string">"github.com/stretchr/testify/assert"</span>

   _ <span class="hljs-string">"github.com/mattn/go-sqlite3"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestBookCatalog</span><span class="hljs-params">(t *testing.T)</span></span> {
   client, err := Open(<span class="hljs-string">"sqlite3"</span>, <span class="hljs-string">"file:book-catalog.db?cache=shared&amp;_fk=1"</span>)

   assert.NoErrorf(t, err, <span class="hljs-string">"failed opening connection to sqlite"</span>)
   <span class="hljs-keyword">defer</span> client.Close()

   ctx := context.Background()

   <span class="hljs-comment">// Run the automatic migration tool to create all schema resources.</span>
   err = client.Schema.Create(ctx)
   assert.NoErrorf(t, err, <span class="hljs-string">"failed creating schema resources"</span>)
}
</code></pre>
<p>Then, run the <strong><em>go test -v ./ent</em></strong>, it will create a schema with empty books table.</p>
<pre><code class="lang-bash">➜  book-catalog git:(main) ✗ go <span class="hljs-built_in">test</span> -v ./ent
=== RUN   TestBookCatalog
--- PASS: TestBookCatalog (0.00s)
PASS
ok      github.com/pratikjagrut/book-catalog/ent    0.660s
</code></pre>
<p><strong>Create database schema:</strong></p>
<p>With the basic setup in place, we are now ready to expand our Book entity by adding fields and proceeding with building queries and mutations.</p>
<p>Let’s define a schema for our database:</p>
<p>The author has the following properties:</p>
<ul>
<li><p><strong>ID</strong>: A unique identifier for the book. Auto-generated.</p>
</li>
<li><p><strong>Name: Name of the author</strong></p>
</li>
<li><p><strong>Email: Email address of the author</strong></p>
</li>
</ul>
<p>In addition, we need to establish a relationship, or edge, between the Author and Book entities. In this scenario, an author can write multiple books, creating a One-to-Many (1-&gt;M) relationship.</p>
<p>Add the following fields and edges to the <strong>ent/schema/author.go file</strong>.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> schema

<span class="hljs-keyword">import</span> (
   <span class="hljs-string">"entgo.io/ent"</span>
   <span class="hljs-string">"entgo.io/ent/schema/edge"</span>
   <span class="hljs-string">"entgo.io/ent/schema/field"</span>
)

<span class="hljs-comment">// Author holds the schema definition for the Author entity.</span>
<span class="hljs-keyword">type</span> Author <span class="hljs-keyword">struct</span> {
   ent.Schema
}

<span class="hljs-comment">// Fields of the Author.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Author)</span> <span class="hljs-title">Fields</span><span class="hljs-params">()</span> []<span class="hljs-title">ent</span>.<span class="hljs-title">Field</span></span> {
   <span class="hljs-keyword">return</span> []ent.Field{
       field.String(<span class="hljs-string">"name"</span>),
       field.String(<span class="hljs-string">"email"</span>),
   }
}

<span class="hljs-comment">// Edges of the Author.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Author)</span> <span class="hljs-title">Edges</span><span class="hljs-params">()</span> []<span class="hljs-title">ent</span>.<span class="hljs-title">Edge</span></span> {
   <span class="hljs-keyword">return</span> []ent.Edge{
       edge.To(<span class="hljs-string">"books"</span>, Book.Type),
   }
}
</code></pre>
<p>The book has the following properties:</p>
<ul>
<li><p><strong>ID</strong>: A unique identifier for the book. Auto-generated.</p>
</li>
<li><p><strong>Title</strong>: The title or name of the book.</p>
</li>
<li><p><strong>Genre</strong>: The genre or category to which the book belongs.</p>
</li>
<li><p><strong>PublicationDate</strong>: The date when the book was published.</p>
</li>
<li><p><strong>ISBN</strong>: The International Standard Book Number assigned to the book.</p>
</li>
<li><p><strong>CreatedAt</strong>: The date and time of record creation in the database.</p>
</li>
</ul>
<p>Here, the relation between the book and the author will be <strong><em>many-to-one.</em></strong> So we’ll create an inverse edge.</p>
<p>Now, add these fields to the <strong>ent/schema/book.go file</strong>.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> schema

<span class="hljs-keyword">import</span> (
   <span class="hljs-string">"time"</span>

   <span class="hljs-string">"entgo.io/ent"</span>
   <span class="hljs-string">"entgo.io/ent/schema/edge"</span>
   <span class="hljs-string">"entgo.io/ent/schema/field"</span>
)

<span class="hljs-comment">// Book holds the schema definition for the Book entity.</span>
<span class="hljs-keyword">type</span> Book <span class="hljs-keyword">struct</span> {
   ent.Schema
}

<span class="hljs-comment">// Fields of the Book.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Book)</span> <span class="hljs-title">Fields</span><span class="hljs-params">()</span> []<span class="hljs-title">ent</span>.<span class="hljs-title">Field</span></span> {
   <span class="hljs-keyword">return</span> []ent.Field{
       field.String(<span class="hljs-string">"title"</span>).NotEmpty(),
       field.String(<span class="hljs-string">"genre"</span>).NotEmpty(),
       field.String(<span class="hljs-string">"publication_date"</span>).NotEmpty(),
       field.String(<span class="hljs-string">"isbn"</span>).NotEmpty(),
       field.Time(<span class="hljs-string">"created_at"</span>).Default(time.Now()),
   }
}

<span class="hljs-comment">// Edges of the Book.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Book)</span> <span class="hljs-title">Edges</span><span class="hljs-params">()</span> []<span class="hljs-title">ent</span>.<span class="hljs-title">Edge</span></span> {
   <span class="hljs-keyword">return</span> []ent.Edge{
       edge.From(<span class="hljs-string">"author"</span>, Author.Type).
           Ref(<span class="hljs-string">"books"</span>).
           Unique(),
   }
}
</code></pre>
<p><strong>Create mutations and queries</strong></p>
<p>Once again, let's run <strong><em>go generate ./ent</em></strong> to generate the necessary mutations for the fields we defined in our Author and Book entity and check schema with <strong><em>go run -mod=mod</em></strong> <a target="_blank" href="http://entgo.io/ent/cmd/ent"><strong><em>entgo.io/ent/cmd/ent</em></strong></a> <strong><em>describe ./ent/schema</em></strong> command.</p>
<pre><code class="lang-bash">➜ go run -mod=mod entgo.io/ent/cmd/ent describe ./ent/schema
Author:
    +-------+--------+--------+----------+----------+---------+---------------+-----------+------------------------+------------+---------+
    | Field |  Type  | Unique | Optional | Nillable | Default | UpdateDefault | Immutable |       StructTag        | Validators | Comment |
    +-------+--------+--------+----------+----------+---------+---------------+-----------+------------------------+------------+---------+
    | id    | int    | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"id,omitempty"</span>    |          0 |         |
    | name  | string | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"name,omitempty"</span>  |          0 |         |
    | email | string | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"email,omitempty"</span> |          0 |         |
    +-------+--------+--------+----------+----------+---------+---------------+-----------+------------------------+------------+---------+
    +-------+------+---------+---------+----------+--------+----------+---------+
    | Edge  | Type | Inverse | BackRef | Relation | Unique | Optional | Comment |
    +-------+------+---------+---------+----------+--------+----------+---------+
    | books | Book | <span class="hljs-literal">false</span>   |         | O2M      | <span class="hljs-literal">false</span>  | <span class="hljs-literal">true</span>     |         |
    +-------+------+---------+---------+----------+--------+----------+---------+

Book:
    +------------------+-----------+--------+----------+----------+---------+---------------+-----------+-----------------------------------+------------+---------+
    |      Field       |   Type    | Unique | Optional | Nillable | Default | UpdateDefault | Immutable |             StructTag             | Validators | Comment |
    +------------------+-----------+--------+----------+----------+---------+---------------+-----------+-----------------------------------+------------+---------+
    | id               | int       | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"id,omitempty"</span>               |          0 |         |
    | title            | string    | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"title,omitempty"</span>            |          1 |         |
    | genre            | string    | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"genre,omitempty"</span>            |          1 |         |
    | publication_date | string    | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"publication_date,omitempty"</span> |          1 |         |
    | isbn             | string    | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>   | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"isbn,omitempty"</span>             |          1 |         |
    | created_at       | time.Time | <span class="hljs-literal">false</span>  | <span class="hljs-literal">false</span>    | <span class="hljs-literal">false</span>    | <span class="hljs-literal">true</span>    | <span class="hljs-literal">false</span>         | <span class="hljs-literal">false</span>     | json:<span class="hljs-string">"created_at,omitempty"</span>       |          0 |         |
    +------------------+-----------+--------+----------+----------+---------+---------------+-----------+-----------------------------------+------------+---------+
    +--------+--------+---------+---------+----------+--------+----------+---------+
    |  Edge  |  Type  | Inverse | BackRef | Relation | Unique | Optional | Comment |
    +--------+--------+---------+---------+----------+--------+----------+---------+
    | author | Author | <span class="hljs-literal">true</span>    | books   | M2O      | <span class="hljs-literal">true</span>   | <span class="hljs-literal">true</span>     |         |
    +--------+--------+---------+---------+----------+--------+----------+---------+
</code></pre>
<p>With Ent, creating migrations and performing common operations such as creating a record or fetching records is straightforward and practical.</p>
<p>To create a new record in the database, we can simply call the following code:</p>
<pre><code class="lang-go">author, _ := client.Author.Create().
       SetName(<span class="hljs-string">"J. K. Rowling"</span>).
       SetEmail(<span class="hljs-string">"jk@gmail.com"</span>).
       Save(context.Background())

book, _ := client.Book.Create().
       SetTitle(<span class="hljs-string">"The Ink Black Heart"</span>).
       SetGenre(<span class="hljs-string">"Mystery"</span>).
       SetIsbn(<span class="hljs-string">"9780316413138"</span>).
       SetPublicationDate(<span class="hljs-string">"30 August 2022"</span>).
       SetAuthor(author).
       Save(context.Background())
</code></pre>
<p>This code snippet creates a new author and book record and adds the edge using the <strong><em>SetAuthor</em></strong> method.</p>
<p>To fetch all the books from the database, we can use the following code:</p>
<pre><code class="lang-go">books, err := client.Book.Query().All(ctx)
</code></pre>
<p>This code retrieves all the Book records stored in the database.</p>
<p>Ent provides many more useful functions and options for creating, fetching, and manipulating data in the database. Such features make database operations more manageable and efficient. I encourage you to explore the <a target="_blank" href="https://entgo.io/docs/getting-started">Ent documentation</a> for a deeper understanding of Ent's capabilities and how to make the most of it in your projects.</p>
<p><strong>Test ent setup</strong></p>
<p>Let’s update our <strong>ent/book-catalog_test.go</strong> with migrations.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> ent

<span class="hljs-keyword">import</span> (
   <span class="hljs-string">"context"</span>
   <span class="hljs-string">"testing"</span>

   <span class="hljs-string">"github.com/stretchr/testify/assert"</span>

   _ <span class="hljs-string">"github.com/mattn/go-sqlite3"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestBookCatalog</span><span class="hljs-params">(t *testing.T)</span></span> {
   <span class="hljs-comment">// client, err := Open("sqlite3", "file:book-catalog.db?cache=shared&amp;_fk=1")</span>
   client, err := Open(<span class="hljs-string">"sqlite3"</span>, <span class="hljs-string">"file:ent?mode=memory&amp;cache=shared&amp;_fk=1"</span>)
   assert.NoErrorf(t, err, <span class="hljs-string">"failed opening connection to sqlite"</span>)
   <span class="hljs-keyword">defer</span> client.Close()

   ctx := context.Background()

   <span class="hljs-comment">// Run the automatic migration tool to create all schema resources.</span>
   err = client.Schema.Create(ctx)
   assert.NoErrorf(t, err, <span class="hljs-string">"failed creating schema resources"</span>)

   author, err := client.Author.Create().
       SetName(<span class="hljs-string">"J. K. Rowling"</span>).
       SetEmail(<span class="hljs-string">"jk@gmail.com"</span>).
       Save(ctx)
   assert.NoError(t, err)

   _, err = client.Book.Create().
       SetTitle(<span class="hljs-string">"The Ink Black Heart"</span>).
       SetGenre(<span class="hljs-string">"Mystery"</span>).
       SetIsbn(<span class="hljs-string">"9780316413138"</span>).
       SetPublicationDate(<span class="hljs-string">"30 August 2022"</span>).
       SetAuthor(author).
       Save(ctx)
   assert.NoError(t, err)

   author, err = client.Author.Create().
       SetName(<span class="hljs-string">"George R. R. Martin"</span>).
       SetEmail(<span class="hljs-string">"grrm@gmail.com"</span>).
       Save(ctx)
   assert.NoError(t, err)

   _, err = client.Book.Create().
       SetTitle(<span class="hljs-string">"A Game of Thrones"</span>).
       SetGenre(<span class="hljs-string">"Fantasy Fiction"</span>).
       SetIsbn(<span class="hljs-string">"9780553593716"</span>).
       SetPublicationDate(<span class="hljs-string">"1 August 1996"</span>).
       SetAuthor(author).
       Save(ctx)
   assert.NoError(t, err)

   books, err := client.Book.Query().All(ctx)
   assert.NoError(t, err)
   assert.Equal(t, <span class="hljs-built_in">len</span>(books), <span class="hljs-number">2</span>)
}
</code></pre>
<p>Now run the go test and it should pass.</p>
<pre><code class="lang-bash">➜  book-catalog git:(main) ✗ go <span class="hljs-built_in">test</span> -v ./ent
=== RUN   TestBookCatalog
--- PASS: TestBookCatalog (0.00s)
PASS
ok      github.com/pratikjagrut/book-catalog/ent
</code></pre>
<h2 id="heading-setup-graphql-with-ent">Setup GraphQL with Ent</h2>
<p>Now, let's take our Ent setup with the SQLite database a step further by integrating GraphQL. This integration will provide a more advanced and practical way to handle database queries.</p>
<p>By integrating GraphQL with Ent, we can leverage GraphQL's flexible querying capabilities to efficiently retrieve data. With the help of <a target="_blank" href="https://github.com/99designs/gqlgen">99designs /gqlgen</a>, a powerful Go library, we can automatically generate GraphQL schemas and resolvers based on our Ent data models. This simplifies the process of building GraphQL APIs, allowing us to focus on defining schemas and writing resolver functions.</p>
<h4 id="heading-install-and-configure-entgql"><strong>Install and configure entgql</strong></h4>
<p>Ent offers a convenient extension called <a target="_blank" href="https://pkg.go.dev/entgo.io/contrib/entgql">contrib/entgql</a> that allows it to generate GraphQL schemas seamlessly. By installing and utilizing this extension, we can effortlessly generate GraphQL schemas based on our Ent data models.</p>
<p>To get started with contrib/entgql, you can install it by running the following command:</p>
<pre><code class="lang-bash">go get entgo.io/contrib/entgql
</code></pre>
<p>To enable query and mutation capabilities for the Autor and Book schema using Ent and contrib/entgql, we need to add the following annotations to the schema of both entities.</p>
<p>Add the following code to <strong>ent/schema/author.go:</strong></p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Author)</span> <span class="hljs-title">Annotations</span><span class="hljs-params">()</span> []<span class="hljs-title">schema</span>.<span class="hljs-title">Annotation</span></span> {
   <span class="hljs-keyword">return</span> []schema.Annotation{
       entgql.QueryField(),
       entgql.Mutations(entgql.MutationCreate()),
   }
}
</code></pre>
<p>Add the following code to <strong><em>ent/schema/book.go</em></strong>:</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(Book)</span> <span class="hljs-title">Annotations</span><span class="hljs-params">()</span> []<span class="hljs-title">schema</span>.<span class="hljs-title">Annotation</span></span> {
   <span class="hljs-keyword">return</span> []schema.Annotation{
       entgql.QueryField(),
       entgql.Mutations(entgql.MutationCreate()),
   }
}
</code></pre>
<p>With the annotations we added, we're telling contrib/entgql to generate essential GraphQL query and mutation fields for our entities to fetch and create data.</p>
<p>Let's create a new file named <strong>ent/entc.go</strong> and add the following content:</p>
<pre><code class="lang-go"><span class="hljs-comment">//go:build ignore</span>

<span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"log"</span>

    <span class="hljs-string">"entgo.io/ent/entc"</span>
    <span class="hljs-string">"entgo.io/ent/entc/gen"</span>
    <span class="hljs-string">"entgo.io/contrib/entgql"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    ex, err := entgql.NewExtension(
        <span class="hljs-comment">// Generate a GraphQL schema for the Ent schema</span>
        <span class="hljs-comment">// and save it as "ent.graphql".</span>
        entgql.WithSchemaGenerator(),
        entgql.WithSchemaPath(<span class="hljs-string">"ent.graphql"</span>),
    )
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatalf(<span class="hljs-string">"failed to create entgql extension: %v"</span>, err)
    }
    opts := []entc.Option{
        entc.Extensions(ex),
    }
    <span class="hljs-keyword">if</span> err := entc.Generate(<span class="hljs-string">"./ent/schema"</span>, &amp;gen.Config{}, opts...); err != <span class="hljs-literal">nil</span> {
        log.Fatalf(<span class="hljs-string">"failed to run ent codegen: %v"</span>, err)
    }
}
</code></pre>
<p>In this code, we have a <strong>main</strong> function that performs the Ent code generation. We use the <strong>entgql</strong> extension to generate a GraphQL schema based on our Ent schema. The generated GraphQL schema will be saved as <strong>ent.graphql</strong>.</p>
<p>It's worth noting that the <strong>ent/entc.go</strong> file is ignored during the build process using a <strong>//go:build ignore</strong> tag. To execute this file, we will utilize the <strong>go generate</strong> command, which is triggered by the <strong>generate.go</strong> file in your project.</p>
<p>Remove the <strong>ent/generate.go</strong> file and create a new one in the <strong>root of the project</strong> with the following contents. In the next steps, gqlgen commands will be added to this file as well.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> bookcatalog

<span class="hljs-comment">//go:generate go run -mod=mod ./ent/entc.go</span>
</code></pre>
<h4 id="heading-running-schema-generation"><strong>Running schema generation</strong></h4>
<p>Once you have installed and configured <strong>entgql</strong>, you can execute the code generation process by running the following command:\</p>
<pre><code class="lang-bash">go generate .
</code></pre>
<p><strong><em>Note</em></strong>: If you encounter package inconsistencies or missing package errors in your IDE after running <strong><em>go generate</em></strong>, you can resolve them by running <strong><em>go mod tidy</em></strong>.</p>
<p>You'll notice a new file was created named <strong>ent.graphql</strong>:</p>
<pre><code class="lang-graphql">directive <span class="hljs-meta">@goField</span>(<span class="hljs-symbol">forceResolver:</span> Boolean, <span class="hljs-symbol">name:</span> String) <span class="hljs-keyword">on</span> FIELD_DEFINITION | INPUT_FIELD_DEFINITION
directive <span class="hljs-meta">@goModel</span>(<span class="hljs-symbol">model:</span> String, <span class="hljs-symbol">models:</span> [String!]) <span class="hljs-keyword">on</span> OBJECT | INPUT_OBJECT | SCALAR | ENUM | INTERFACE | UNION
<span class="hljs-keyword">type</span> Author <span class="hljs-keyword">implements</span> Node {
 <span class="hljs-symbol">id:</span> ID!
 <span class="hljs-symbol">name:</span> String!
 <span class="hljs-symbol">email:</span> String!
 <span class="hljs-symbol">books:</span> [Book!]
}
<span class="hljs-keyword">type</span> Book <span class="hljs-keyword">implements</span> Node {
 <span class="hljs-symbol">id:</span> ID!
 <span class="hljs-symbol">title:</span> String!
 <span class="hljs-symbol">genre:</span> String!
 <span class="hljs-symbol">publicationDate:</span> String!
 <span class="hljs-symbol">isbn:</span> String!
 <span class="hljs-symbol">createdAt:</span> Time!
 <span class="hljs-symbol">author:</span> Author
}
<span class="hljs-string">""</span><span class="hljs-string">"
CreateAuthorInput is used for create Author object.
Input was generated by ent.
"</span><span class="hljs-string">""</span>
<span class="hljs-keyword">input</span> CreateAuthorInput {
 <span class="hljs-symbol">name:</span> String!
 <span class="hljs-symbol">email:</span> String!
 <span class="hljs-symbol">bookIDs:</span> [ID!]
}
<span class="hljs-string">""</span><span class="hljs-string">"
CreateBookInput is used for create Book object.
Input was generated by ent.
"</span><span class="hljs-string">""</span>
<span class="hljs-keyword">input</span> CreateBookInput {
 <span class="hljs-symbol">title:</span> String!
 <span class="hljs-symbol">genre:</span> String!
 <span class="hljs-symbol">publicationDate:</span> String!
 <span class="hljs-symbol">isbn:</span> String!
 <span class="hljs-symbol">createdAt:</span> Time
 <span class="hljs-symbol">authorID:</span> ID
}
<span class="hljs-string">""</span><span class="hljs-string">"
...</span>
</code></pre>
<h4 id="heading-install-and-configure-gqlgen"><strong>Install and configure gqlgen</strong></h4>
<p>Install <strong>99designs/gqlgen</strong>:</p>
<pre><code class="lang-bash">go get github.com/99designs/gqlgen
</code></pre>
<p>To configure the <strong>gqlgen</strong> package, we need to create a <strong>gqlgen.yml</strong> file in the root directory of our project. This file is automatically loaded by <strong>gqlgen</strong> and provides the necessary configuration for generating the GraphQL server code.</p>
<p>Let's add the <strong>gqlgen.yml</strong> file to the root of our project and follow the comments within the file to understand the meaning of each configuration directive.</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># schema tells gqlgen where the GraphQL schema is located.</span>
<span class="hljs-attr">schema:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">ent.graphql</span>

<span class="hljs-comment"># resolver reports where the resolver implementations go.</span>
<span class="hljs-attr">resolver:</span>
<span class="hljs-attr">layout:</span> <span class="hljs-string">follow-schema</span>
<span class="hljs-attr">dir:</span> <span class="hljs-string">.</span>

<span class="hljs-comment"># gqlgen will search for any type names in the schema in these go packages</span>
<span class="hljs-comment"># if they match it will use them, otherwise it will generate them.</span>

<span class="hljs-comment"># autobind tells gqngen to search for any type names in the GraphQL schema in the</span>
<span class="hljs-comment"># provided package. If they match it will use them, otherwise it will generate new.</span>
<span class="hljs-attr">autobind:</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">github.com/pratikjagrut/book-catalog/ent</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">github.com/pratikjagrut/book-catalog/ent/author</span>
<span class="hljs-bullet">-</span> <span class="hljs-string">github.com/pratikjagrut/book-catalog/ent/book</span>

<span class="hljs-comment"># This section declares type mapping between the GraphQL and Go type systems.</span>
<span class="hljs-attr">models:</span>
<span class="hljs-comment"># Defines the ID field as Go 'int'.</span>
<span class="hljs-attr">ID:</span>
  <span class="hljs-attr">model:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">github.com/99designs/gqlgen/graphql.IntID</span>
<span class="hljs-attr">Node:</span>
  <span class="hljs-attr">model:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">github.com/pratikjagrut/book-catalog/ent.Noder</span>
</code></pre>
<p>To inform Ent about the <strong>gqlgen</strong> configuration, we need to make a modification to the <strong>ent/entc.go</strong> file. We will pass the <strong>entgql.WithConfigPath("gqlgen.yml")</strong> argument to the <strong>entgql.NewExtension()</strong> function.</p>
<p>Open the <strong>ent/entc.go</strong> file and copy and paste the following code:</p>
<pre><code class="lang-go"><span class="hljs-comment">//go:build ignore</span>

<span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
   <span class="hljs-string">"log"</span>

   <span class="hljs-string">"entgo.io/contrib/entgql"</span>
   <span class="hljs-string">"entgo.io/ent/entc"</span>
   <span class="hljs-string">"entgo.io/ent/entc/gen"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
   ex, err := entgql.NewExtension(
       <span class="hljs-comment">// Tell Ent to generate a GraphQL schema for</span>
       <span class="hljs-comment">// the Ent schema in a file named ent.graphql.</span>
       entgql.WithSchemaGenerator(),
       entgql.WithSchemaPath(<span class="hljs-string">"ent.graphql"</span>),
       entgql.WithConfigPath(<span class="hljs-string">"gqlgen.yml"</span>),
   )
   <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
       log.Fatalf(<span class="hljs-string">"creating entgql extension: %v"</span>, err)
   }
   opts := []entc.Option{
       entc.Extensions(ex),
   }
   <span class="hljs-keyword">if</span> err := entc.Generate(<span class="hljs-string">"./ent/schema"</span>, &amp;gen.Config{}, opts...); err != <span class="hljs-literal">nil</span> {
       log.Fatalf(<span class="hljs-string">"running ent codegen: %v"</span>, err)
   }
}
</code></pre>
<p>Add the gqlgen generate command <strong><em>//go:generate go run -mod=mod</em></strong> <a target="_blank" href="http://github.com/99designs/gqlgen"><strong><em>github.com/99designs/gqlgen</em></strong></a> to the <strong>generate.go</strong> file:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> bookcatalog

<span class="hljs-comment">//go:generate go run -mod=mod ./ent/entc.go</span>
<span class="hljs-comment">//go:generate go run -mod=mod github.com/99designs/gqlgen</span>
</code></pre>
<p>Now, we're ready to run go generate to trigger ent and gqlgen code generation. Execute the <strong>go generate</strong> command from the root of the project and you may notice new files created.</p>
<pre><code class="lang-bash">➜  book-catalog git:(main) ✗ tree -L 1
.
├── ent
├── ent.graphql
├── ent.resolvers.go
├── generate.go
├── generated.go
├── go.mod
├── go.sum
├── gqlgen.yml
└── resolver.go

1 directory, 8 files
</code></pre>
<h2 id="heading-the-server">The Server</h2>
<p>In order to build the GraphQL server, we need to set up the main schema Resolver as defined in <strong>resolver.go</strong>. The gqlgen library provides the flexibility to modify the generated Resolver and add dependencies to it.</p>
<p>To include the <strong>ent.Client</strong> as a dependency, you can add the following code snippet to <strong>resolver.go</strong>:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> bookcatalog

<span class="hljs-keyword">import</span> (
   <span class="hljs-string">"github.com/pratikjagrut/book-catalog/ent"</span>

   <span class="hljs-string">"github.com/99designs/gqlgen/graphql"</span>
)

<span class="hljs-comment">// Resolver is the resolver root.</span>
<span class="hljs-keyword">type</span> Resolver <span class="hljs-keyword">struct</span>{ client *ent.Client }

<span class="hljs-comment">// NewSchema creates a graphql executable schema.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewSchema</span><span class="hljs-params">(client *ent.Client)</span> <span class="hljs-title">graphql</span>.<span class="hljs-title">ExecutableSchema</span></span> {
   <span class="hljs-keyword">return</span> NewExecutableSchema(Config{
       Resolvers: &amp;Resolver{client},
   })
}
</code></pre>
<p>In the above code, we define a Resolver struct with a field named client of type <strong>*ent.Client</strong>. This allows us to use the ent.Client as a dependency within our Resolver.</p>
<p>The NewSchema function is responsible for creating the GraphQL executable schema. It takes the ent.Client as a parameter and initializes the Resolver with it.</p>
<p>By adding this code to resolver.go, we ensure that our GraphQL server has access to the ent.Client and can utilize it for database operations.</p>
<p>To create the entry point for our GraphQL server, we'll start by creating a new directory called <strong>server</strong>. Inside this directory, we'll create a <strong>main.go</strong> file, which will serve as the entry point for our GraphQL server.</p>
<pre><code class="lang-bash">mkdir server
touch server/main.go
</code></pre>
<p>Run the server using the command below, and open <a target="_blank" href="http://localhost:8081">localhost:8081</a> to access the Graph<em>i</em>QL IDE.</p>
<pre><code class="lang-bash">go run server/main.go
</code></pre>
<p><img src="https://lh4.googleusercontent.com/nkoFjRL5sD_hQ7yqOOqxHFqBxnhI3CaHb5Qk9IsY48yVS-pYVs3Fw_zcYpE3FftExo6Qjbb4f7CMnfi_hJxkT0NzC01zQYf4yibRb-sLClAvy11QBsP2tWaSymaVUWDPx_sA4gMGSmPFMatyiDUQYiY" alt /></p>
<h3 id="heading-query-data">Query Data</h3>
<p>When you run the GraphQL server using UI on <a target="_blank" href="http://localhost:8081">localhost:8081</a> and send a query or mutation request, you will notice a "not implemented" message with a panic error displayed in the terminal. This occurs because we have not yet implemented the corresponding query and mutation functions in the GraphQL resolver.</p>
<pre><code class="lang-graphql">{
  books {
    title
    author {
      name
    }
    genre
    publicationDate
    isbn
  }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-graphql">{
  <span class="hljs-string">"errors"</span>: [
    {
      <span class="hljs-string">"message"</span>: <span class="hljs-string">"internal system error"</span>,
      <span class="hljs-string">"path"</span>: [
        <span class="hljs-string">"books"</span>
      ]
    }
  ],
  <span class="hljs-string">"data"</span>: <span class="hljs-variable">null</span>
}
</code></pre>
<p>Just replace the following implementation in <strong><em>ent.resolver.go</em></strong> with the following code.</p>
<pre><code class="lang-go"><span class="hljs-comment">// Authors is the resolver for the authors field.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(r *queryResolver)</span> <span class="hljs-title">Authors</span><span class="hljs-params">(ctx context.Context)</span> <span class="hljs-params">([]*ent.Author, error)</span></span> {
   <span class="hljs-keyword">return</span> r.client.Author.Query().All(ctx)
}

<span class="hljs-comment">// Books is the resolver for the books field.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(r *queryResolver)</span> <span class="hljs-title">Books</span><span class="hljs-params">(ctx context.Context)</span> <span class="hljs-params">([]*ent.Book, error)</span></span> {
   <span class="hljs-keyword">return</span> r.client.Book.Query().All(ctx)
}
</code></pre>
<p>Now, restart the server and run the above query again in Graph<em>i</em>QL IDE. This time you should see the output below.</p>
<pre><code class="lang-bash">{
  books {
    title
    author {
      name
    }
    genre
    publicationDate
    isbn
  },

  authors{
    name
  }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"books"</span>: [],
    <span class="hljs-string">"authors"</span>: []
  }
}
</code></pre>
<h3 id="heading-mutating-data">Mutating Data</h3>
<p>As observed in the previous example, our GraphQL schema currently returns an empty list of books and authors. To populate the list with data, we can leverage GraphQL mutations to create new book entries. Fortunately, Ent automatically generates mutations for creating and updating nodes and edges, making this process seamless.</p>
<p>We start by extending our GraphQL schema with custom mutations. Let's create a new file named <strong>book.graphql</strong> and add our Mutation type:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">type</span> Mutation {
 <span class="hljs-comment"># The input and the output are types generated by Ent.</span>
 createAuthor(<span class="hljs-symbol">input:</span> CreateAuthorInput!): Author
 createBook(<span class="hljs-symbol">input:</span> CreateBookInput!): Book
}
</code></pre>
<p>Add the custom GraphQL schema to <strong>gqlgen.yml</strong> configuration:</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># schema tells gqlgen where the GraphQL schema is located.</span>
<span class="hljs-attr">schema:</span>
 <span class="hljs-bullet">-</span> <span class="hljs-string">ent.graphql</span>
 <span class="hljs-bullet">-</span> <span class="hljs-string">book.graphql</span>
</code></pre>
<p>As you can see, gqlgen generated for us a new file named <strong>book.resolvers.go</strong> Copy and paste the following code snippet:</p>
<pre><code class="lang-go"><span class="hljs-comment">// CreateAuthor is the resolver for the createAuthor field.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(r *mutationResolver)</span> <span class="hljs-title">CreateAuthor</span><span class="hljs-params">(ctx context.Context, input ent.CreateAuthorInput)</span> <span class="hljs-params">(*ent.Author, error)</span></span> {
   <span class="hljs-keyword">return</span> r.client.Author.Create().SetInput(input).Save(ctx)
}

<span class="hljs-comment">// CreateBook is the resolver for the createBook field.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(r *mutationResolver)</span> <span class="hljs-title">CreateBook</span><span class="hljs-params">(ctx context.Context, input ent.CreateBookInput)</span> <span class="hljs-params">(*ent.Book, error)</span></span> {
   <span class="hljs-keyword">return</span> r.client.Book.Create().SetInput(input).Save(ctx)
}
</code></pre>
<p>Now, restart the server and run the following mutation query in Graph<em>i</em>QL IDE.</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">mutation</span> CreateBook {
  createAuthor(<span class="hljs-symbol">input:</span> {<span class="hljs-symbol">name:</span> <span class="hljs-string">"J. K. Rowling"</span>, <span class="hljs-symbol">email:</span> <span class="hljs-string">"jk@gmail.com"</span>}){id},
  createBook(<span class="hljs-symbol">input:</span> {<span class="hljs-symbol">title:</span> <span class="hljs-string">"The Ink Black Heart"</span>, 
    <span class="hljs-symbol">genre:</span> <span class="hljs-string">"Mystery"</span>, 
    <span class="hljs-symbol">publicationDate:</span><span class="hljs-string">"30 August 2022"</span>, 
    <span class="hljs-symbol">isbn:</span> <span class="hljs-string">"9780316413138"</span>,
    <span class="hljs-symbol">authorID:</span> <span class="hljs-string">"1"</span>,
  }){id, title, author{name} }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-graphql">{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"createAuthor"</span>: {
      <span class="hljs-string">"id"</span>: <span class="hljs-string">"1"</span>
    },
    <span class="hljs-string">"createBook"</span>: {
      <span class="hljs-string">"id"</span>: <span class="hljs-string">"4294967297"</span>,
      <span class="hljs-string">"title"</span>: <span class="hljs-string">"The Ink Black Heart"</span>,
      <span class="hljs-string">"author"</span>: {
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"J. K. Rowling"</span>
      }
    }
  }
}
</code></pre>
<p>Now let’s query the data:</p>
<pre><code class="lang-graphql">{
  books {
    title
    author {
      name
    }
    genre
    publicationDate
    isbn
  },

  authors{
    name
    email
  }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-graphql">{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"books"</span>: [
      {
        <span class="hljs-string">"title"</span>: <span class="hljs-string">"The Ink Black Heart"</span>,
        <span class="hljs-string">"author"</span>: {
          <span class="hljs-string">"name"</span>: <span class="hljs-string">"J. K. Rowling"</span>
        },
        <span class="hljs-string">"genre"</span>: <span class="hljs-string">"Mystery"</span>,
        <span class="hljs-string">"publicationDate"</span>: <span class="hljs-string">"30 August 2022"</span>,
        <span class="hljs-string">"isbn"</span>: <span class="hljs-string">"9780316413138"</span>
      }
    ],
    <span class="hljs-string">"authors"</span>: [
      {
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"J. K. Rowling"</span>,
        <span class="hljs-string">"email"</span>: <span class="hljs-string">"jk@gmail.com"</span>
      }
    ]
  }
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this blog post, we discovered the power of combining GraphQL and Ent for creating efficient APIs in Go. GraphQL offers flexibility in working with data, while Ent simplifies database management. Integrating these tools enables seamless API development in Go.</p>
<p>We learned how to build a GraphQL server using Ent and explored essential features. Additionally, we leveraged GraphQL for querying and modifying data in the database.</p>
<p>I hope this blog post served as a valuable introduction to GraphQL and Ent, inspiring you to consider them for your future API development projects.</p>
<p>You can find the source code for the project on my <a target="_blank" href="https://github.com/pratikjagrut/book-catalog.git">GitHub</a>.</p>
<p>Thank you for reading, and happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Concurrency in Go (Part-3): sync package primitives]]></title><description><![CDATA[Cond
Sometimes, goroutines need to wait for some data or some kind of signal to be available before executing further. Cond primitive provides the most efficient way to just do that.
Cond implements a condition variable, a rendezvous point for gorout...]]></description><link>https://pratikjagrut.space/concurrency-in-go-part-3-sync-package-primitives</link><guid isPermaLink="true">https://pratikjagrut.space/concurrency-in-go-part-3-sync-package-primitives</guid><category><![CDATA[concurrency-in-go]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[goroutines]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[concurrency]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Sun, 09 Apr 2023 16:12:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/NbgQfUvKFE0/upload/a8bd526c69cf1b624401cfe91c76482c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-cond">Cond</h3>
<p>Sometimes, goroutines need to wait for some data or some kind of signal to be available before executing further. Cond primitive provides the most efficient way to just do that.</p>
<p><strong><em>Cond implements a condition variable, a rendezvous point for goroutines waiting for or announcing the occurrence of an event. - sync package doc.</em></strong></p>
<p>Cond is implemented as a struct with <code>Locker</code> field, and implements 3 methods.</p>
<p>The <code>Broadcast()</code> method of <code>Cond</code> wakes up all goroutines that are waiting on the condition <code>c</code>. The caller may or may not hold the associated mutex <code>c.L</code> while calling this method.</p>
<p>Similarly, the <code>Signal()</code> method of <code>Cond</code> wakes up one goroutine that is waiting on a condition <code>c</code>, if any.</p>
<p>The <code>Wait()</code> method of <code>Cond</code> atomically releases the associated mutex <code>c.L</code> and suspends the execution of the calling goroutine. After resuming the execution, the method re-acquires the mutex before returning. Unlike in other systems, the <code>Wait()</code> the method cannot return unless it is awoken by a call to <code>Broadcast()</code> or <code>Signal()</code>.</p>
<p>Let's see an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-keyword">var</span> done <span class="hljs-keyword">bool</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">reader</span><span class="hljs-params">(i <span class="hljs-keyword">int</span>, c *sync.Cond, wg *sync.WaitGroup)</span></span> {
    fmt.Printf(<span class="hljs-string">"goroutine number %d started\n"</span>, i+<span class="hljs-number">1</span>)
    <span class="hljs-keyword">defer</span> wg.Done()
    c.L.Lock()
    <span class="hljs-keyword">defer</span> c.L.Unlock()
    <span class="hljs-keyword">for</span> !done {
        fmt.Printf(<span class="hljs-string">"goroutine number %d waiting\n"</span>, i+<span class="hljs-number">1</span>)
        c.Wait()
    }
    fmt.Printf(<span class="hljs-string">"goroutine number %d finished\n"</span>, i+<span class="hljs-number">1</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writer</span><span class="hljs-params">(c *sync.Cond, wg *sync.WaitGroup)</span></span> {
    fmt.Println(<span class="hljs-string">"Writer goroutine started"</span>)
    <span class="hljs-keyword">defer</span> wg.Done()
    time.Sleep(<span class="hljs-number">5</span> * time.Second)
    c.L.Lock()
    <span class="hljs-keyword">defer</span> c.L.Unlock()
    done = <span class="hljs-literal">true</span>
    c.Broadcast()
    fmt.Println(<span class="hljs-string">"Writer goroutine is done"</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> wg sync.WaitGroup
    m := &amp;sync.Mutex{}
    c := sync.NewCond(m)
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">2</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> reader(i, c, &amp;wg)
    }
    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">go</span> writer(c, &amp;wg)
    wg.Wait()
}
</code></pre>
<pre><code class="lang-bash">➜ go run main.go
Writer goroutine started
goroutine number 2 started
goroutine number 2 waiting
goroutine number 1 started
goroutine number 1 waiting
Writer goroutine is <span class="hljs-keyword">done</span>
goroutine number 1 finished
goroutine number 2 finished
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/HKfDuXv3vy0"><strong>Run this code in Go Playground</strong></a></p>
<p>In the above example, we wait on a condition <code>for !done{}</code>. All the reader goroutines will be suspended until the writer goroutines update the variable <code>done=true</code> and send the waking-up signal to all suspended goroutines.</p>
<h3 id="heading-once">Once</h3>
<p>The <code>sync.Once</code> type in Go is used to perform a certain operation exactly once in a concurrent setting, regardless of how many times it is called from different goroutines.</p>
<p>The <code>sync.Once</code> type guarantees that the operation is executed only once, even if multiple goroutines attempt to call it concurrently. This is useful when you need to initialize a shared resource that is expensive to create or when you want to ensure that a particular task is executed only once.</p>
<p>The <code>sync.Once</code> the type has a single method, <code>Do(f func())</code>, that takes a function <code>f</code> as an argument. The first call to <code>Do()</code> will execute the function <code>f</code>, and subsequent calls will do nothing. The <code>sync.Once</code> type internally maintains a flag that indicates whether <code>f</code> has been executed or not.</p>
<p>Let's see an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">DBinit</span><span class="hljs-params">()</span></span> {
    fmt.Println(<span class="hljs-string">"Initializing database..."</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> wg sync.WaitGroup
    <span class="hljs-keyword">var</span> once sync.Once

    <span class="hljs-keyword">for</span> i := <span class="hljs-number">1</span>; i &lt; <span class="hljs-number">5</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
            <span class="hljs-keyword">defer</span> wg.Done()
            once.Do(DBinit)
            fmt.Println(<span class="hljs-string">"Database initialized."</span>)
        }()
    }
    wg.Wait()
}
</code></pre>
<pre><code class="lang-bash">➜  go run main.go
Initializing database...
Database initialized.
Database initialized.
Database initialized.
Database initialized.
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/3mG4X8f51GT"><strong>Run this code in Go Playground</strong></a></p>
<h3 id="heading-pool">Pool</h3>
<p>The <code>sync.Pool</code> type in Go enables caching of temporary objects that can be utilized again across multiple goroutines. Essentially, the <code>sync.Pool</code> maintains a finite set of objects that are assigned to the goroutine, and once a goroutine finishes utilizing an object, it is returned to the pool for reuse by another goroutine.</p>
<p>The <code>sync.Pool</code> type works by maintaining a pool of objects that can be accessed and reused by multiple goroutines. We can request new resource objects using <code>Get()</code> the method of <code>sync.Pool</code>. It first checks if there are any objects in the pool. If there are, it returns one of the objects. If not, it creates a new object and returns it. When an object is no longer needed, it can be put back into the pool for future use using <code>Put(x interface{})</code> the method.</p>
<p>Using <code>sync.Pool</code> can significantly reduce the number of objects that need to be garbage collected, which can improve overall performance in Go programs. However, it is important to use <code>sync.Pool</code> judiciously, as it is not always beneficial and can sometimes even hurt performance if not used correctly.</p>
<p>Here's an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> wg sync.WaitGroup
    <span class="hljs-keyword">var</span> bufCount <span class="hljs-keyword">int</span>

    bufPool := &amp;sync.Pool{
        New: <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span> <span class="hljs-title">any</span></span> {
            bufCount++
            buf := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">byte</span>, <span class="hljs-number">1024</span>)
            <span class="hljs-keyword">return</span> &amp;buf
        },
    }

    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000000</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
            <span class="hljs-keyword">defer</span> wg.Done()
            buf := bufPool.Get().(*[]<span class="hljs-keyword">byte</span>)
            bufPool.Put(buf)
        }()
    }

    wg.Wait()
    fmt.Println(bufCount)
}
</code></pre>
<pre><code class="lang-bash">➜  go run main.go
9
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/iXTjC2CWv-Y"><strong>Run this code in Go Playground</strong></a></p>
<p>Next, a <code>sync.Pool</code> is created using the <code>New</code> field, which is a function that creates a new object when the pool is empty. In this case, the New function creates a new <code>byte slice with a length of 1024</code> and returns a pointer to the slice. The function also increments the <code>bufCount</code> variable to keep track of the number of objects created.</p>
<p>Then, a loop is started that creates <code>1 million goroutines</code>. Each goroutine calls the sync.Pool's <code>Get</code> method to retrieve a byte slice from the pool. In the end, the goroutine calls the sync.Pool's <code>Put</code> method to return the byte slice to the pool.</p>
<p><strong><em>If this program were written without using sync.Pool</em></strong>, each goroutine would create its own byte buffer whenever it needed one. This would result in a lot of unnecessary memory allocation and garbage collection, which can be costly in terms of performance.</p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Concurrency in Go (Part-2): sync package primitives]]></title><description><![CDATA[Introduction
Go is primarily designed around Communicating Sequential Processes i.e using channels and select primitives to write concurrent programs, but it also supports the traditional way of writing concurrent code using Memory Access Synchroniza...]]></description><link>https://pratikjagrut.space/concurrency-in-go-part-2-sync-package-primitives</link><guid isPermaLink="true">https://pratikjagrut.space/concurrency-in-go-part-2-sync-package-primitives</guid><category><![CDATA[Go Language]]></category><category><![CDATA[concurrency-in-go]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[goroutines]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Thu, 06 Apr 2023 12:20:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/G2lgiBBzeEM/upload/0f1a0ee43752f4e38452b54d3124dc2e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Go is primarily designed around <strong><em>Communicating Sequential Processes</em></strong> i.e using channels and select primitives to write concurrent programs, but it also supports the traditional way of writing concurrent code using <strong><em>Memory Access Synchronization</em></strong>.</p>
<p>CSP primitives are sufficient for writing concurrent programs in most cases, but if the need arises to do low-level memory access synchronization, the <code>sync package</code> provides primitives for it. The sync package is part of the Go standard library.</p>
<p>sync package's primitives are:</p>
<ul>
<li><p><em>WaitGroup</em></p>
</li>
<li><p><em>Mutex &amp; RWMutex</em></p>
</li>
<li><p><em>Cond</em></p>
</li>
<li><p><em>Once</em></p>
</li>
<li><p><em>Pool</em></p>
</li>
</ul>
<h3 id="heading-waitgroup">WaitGroup</h3>
<p>WaitGroup provides an alternative to using channels and the select statement to wait for goroutines to finish their execution. WaitGroup is preferred when the results of the concurrent process are not important or we've other ways of collecting results from goroutines.</p>
<p>Here's an example of using WaitGroup to block the main goroutine.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"net/http"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchURL</span><span class="hljs-params">(url <span class="hljs-keyword">string</span>, wg *sync.WaitGroup)</span></span> {
    <span class="hljs-keyword">defer</span> wg.Done()
    resp, err := http.Get(url)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        fmt.Println(<span class="hljs-string">"Error:"</span>, err)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-keyword">defer</span> resp.Body.Close()
    fmt.Println(<span class="hljs-string">"URL hit: "</span>, url)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> wg sync.WaitGroup
    urls := []<span class="hljs-keyword">string</span>{
        <span class="hljs-string">"https://www.google.com"</span>,
        <span class="hljs-string">"https://www.youtube.com"</span>,
        <span class="hljs-string">"https://www.amazon.com"</span>,
        <span class="hljs-string">"https://www.linkedin.com"</span>,
    }
    fmt.Println(<span class="hljs-string">"Start executing goroutines!"</span>)
    <span class="hljs-keyword">for</span> _, url := <span class="hljs-keyword">range</span> urls {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> fetchURL(url, &amp;wg)
    }
    fmt.Println(<span class="hljs-string">"Outside of for loop"</span>)
    wg.Wait()
    fmt.Println(<span class="hljs-string">"All goroutines executed successfully!"</span>)
}
</code></pre>
<pre><code class="lang-bash">➜  go run main.go
Start executing goroutines!
Outside of <span class="hljs-keyword">for</span> loop
URL hit:  https://www.youtube.com
URL hit:  https://www.google.com
URL hit:  https://www.amazon.com
URL hit:  https://www.linkedin.com
All goroutines executed successfully!
</code></pre>
<p>In the program above, the order of execution of the goroutines is visible in the output. First, the statement before the for loop was executed. Then, inside the for loop, we created four goroutines and before goroutines could finish executing, the for loop exited and the statement after the for loop was executed.</p>
<p>In the above program, we used WaitGroup to synchronise the goroutine execution and block the main goroutine. We incremented the counter by calling <code>wg.Add(1)</code> each time we created a new goroutine. Once a goroutine is completed, we decremented the counter by calling <code>wg.Done()</code>. We used <code>wg.Wait()</code> to pause the main goroutine. <code>wg.Wait()</code> stops the program from continuing until the counter reaches 0, indicating that all goroutines had finished executing.</p>
<h3 id="heading-mutex-andamp-rwmutex">Mutex &amp; RWMutex</h3>
<p>The simultaneous access of shared resources by multiple parallel processes can result in inconsistency in the data or the outcomes of those processes. This inconsistency is referred to as a Race condition.</p>
<p>For example: If a program has multiple goroutines, which are trying to read and write the shared variable. In this case, there is no way to know which goroutine will access the variable first. It may happen that one goroutine is reading that variable and at the same time, another goroutine updates the data on the variable, this may lead to incorrect behaviour of the program. This situation is called a Data Race.</p>
<p>Let's understand it with code:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> wg sync.WaitGroup
    count := <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
            count++
            wg.Done()
        }()
    }
    wg.Wait()
    fmt.Println(<span class="hljs-string">"Final Count: "</span>, count)
}
</code></pre>
<p>In the above example, we've got a count variable that is accessed by all the routines. Now when we run the program we see a different final count. But as we were running for loop 1000 times we should get a count equal to 1000, but that's not the case. There is some inconsistency in the data.</p>
<pre><code class="lang-bash">➜  go run main.go       
Final Count:  981
➜  go run main.go
Final Count:  985
➜  go run main.go
Final Count:  979
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/hpMwsnxvcDi">Run this code in Go Playground</a></p>
<p>In Go, channels are the preferred way to share data by communicating, but if you must use the shared memory then we need to make sure that Memory Access is Synchronised.</p>
<h4 id="heading-mutex">Mutex</h4>
<p>To solve the above issue we use <code>Mutex</code>. Mutex stands for mutual exclusion. Mutex is a way to guard or control the Memory Access Synchronization.</p>
<p>In Go, Mutex is implemented as a struct that contains a flag that indicates whether the lock is currently held by a goroutine or not. If the lock is not held, a goroutine can acquire the lock by calling the <code>Lock()</code> method on the Mutex. If the lock is already held by another goroutine, the calling goroutine will be blocked until the lock is released.</p>
<p>When a goroutine holds the lock, it has exclusive access to the shared resource and can modify it without any interference from other goroutines. Once the goroutine is done with the shared resource, it can release the lock by calling the <code>Unlock()</code> method on Mutex.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> wg sync.WaitGroup
    <span class="hljs-keyword">var</span> lock sync.Mutex

    count := <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
            lock.Lock()
            count++
            lock.Unlock()
            wg.Done()
        }()
    }
    wg.Wait()
    fmt.Println(<span class="hljs-string">"Final Count: "</span>, count)
}
</code></pre>
<pre><code class="lang-bash">➜  go run main.go
Final Count:  1000
➜  go run main.go
Final Count:  1000
➜  go run main.go
Final Count:  1000
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/ECUZm6CC8XC">Run this code in Go Playground</a></p>
<p>In the above example, we're using a mutex, we're locking and unlocking our critical section of code. We apply a lock before the goroutine accesses the count variable. This way only one goroutine can access the count variable and other goroutines will be waiting for the count variable to be unlocked to gain access. This is how mutex synchronises the shared memory access.</p>
<p>Mutex is useful for scenarios where a shared resource needs to be accessed by multiple goroutines in a mutually exclusive manner. However, <strong><em>it can be inefficient in scenarios where there are many read operations and fewer write operations, as it allows only one goroutine to hold the lock at a time, regardless of whether it is reading or writing</em></strong>. In such scenarios, Go provides a more efficient primitive called RWMutex.</p>
<h4 id="heading-rwmutex">RWMutex</h4>
<p>The Go's sync package also provides RWMutex with traditional Mutex. RWMutex stands for <strong><em>Reader/Writer mutual exclusion</em></strong>.</p>
<p><strong><em>The lock can be held by an arbitrary number of readers or a single writer. - sync package doc.</em></strong></p>
<p>It is a type of lock that allows multiple readers to access a shared resource concurrently, but only one writer to modify it at a time.</p>
<p>When a reader wants to access the shared resource, it first calls the <code>RLock()</code> method on the RWMutex. This method acquires a read lock, which allows multiple readers to access the resource simultaneously. To release the lock it calls the <code>RUnlock()</code> method. If a writer holds the lock, the reader must wait until the writer releases it.</p>
<p>When a writer wants to modify the shared resource, it calls the <code>Lock()</code> method on the RWMutex. This method acquires a write lock, which prevents other readers and writers from accessing the resource until the writer calls <code>Unlock()</code> and releases the lock. If readers are holding the lock, the writer must wait until all readers have released it.</p>
<p>Let's see an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    m := &amp;sync.RWMutex{}
    <span class="hljs-keyword">var</span> wg sync.WaitGroup

    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">5</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> readerFunction(&amp;wg, m)
    }
    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">go</span> writerFunction(&amp;wg, m)

    wg.Wait()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writerFunction</span><span class="hljs-params">(wg *sync.WaitGroup, m *sync.RWMutex)</span></span> {
    <span class="hljs-keyword">defer</span> wg.Done()
    fmt.Println(<span class="hljs-string">"Writer acquires lock"</span>)
    m.Lock()
    m.Unlock()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">readerFunction</span><span class="hljs-params">(wg *sync.WaitGroup, m *sync.RWMutex)</span></span> {
    <span class="hljs-keyword">defer</span> wg.Done()
    fmt.Println(<span class="hljs-string">"Reader acquires lock"</span>)
    m.RLock()
    m.RUnlock()
}
</code></pre>
<pre><code class="lang-bash">➜  go run main.go
Reader acquires lock
Writer acquires lock
Reader acquires lock
Reader acquires lock
Reader acquires lock
Reader acquires lock
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/nooyW5TDco1">Run this code in Go Playground</a></p>
<h4 id="heading-mutex-vs-rwmutex-which-one-to-use">Mutex VS RWMutex which one to use?</h4>
<p>In scenarios where more read operations need to be performed, then RWMutex is an efficient choice because it lets multiple reader goroutines acquire locks simultaneously. This reduces the waiting time for reader goroutines significantly and expedites the overall execution of the program.</p>
<p>Following is an example that shows the difference in execution time for Mutex and RWMutex programs:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    m := &amp;sync.Mutex{}
    <span class="hljs-keyword">var</span> wg sync.WaitGroup

    start := time.Now()
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> readerFunction(&amp;wg, m)
    }
    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">go</span> writerFunction(&amp;wg, m)

    wg.Wait()
    fmt.Println(<span class="hljs-string">"Total execution time: "</span>, time.Since(start))
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writerFunction</span><span class="hljs-params">(wg *sync.WaitGroup, m *sync.Mutex)</span></span> {
    <span class="hljs-keyword">defer</span> wg.Done()
    m.Lock()
    m.Unlock()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">readerFunction</span><span class="hljs-params">(wg *sync.WaitGroup, m *sync.Mutex)</span></span> {
    <span class="hljs-keyword">defer</span> wg.Done()
    m.Lock()
    time.Sleep(<span class="hljs-number">1</span> * time.Second)
    m.Unlock()
}
</code></pre>
<pre><code class="lang-bash">➜  go run main.go
Total execution time:  3.003424166s
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/N_SeF4wJtk2">Run this code in Go Playground</a></p>
<p>The above program uses Mutex for synchronisation and it takes <code>3.003424166s</code> to execute. Let's try the same program with RWMutex.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sync"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    m := &amp;sync.RWMutex{}
    <span class="hljs-keyword">var</span> wg sync.WaitGroup

    start := time.Now()
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">3</span>; i++ {
        wg.Add(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">go</span> readerFunction(&amp;wg, m)
    }
    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">go</span> writerFunction(&amp;wg, m)

    wg.Wait()
    fmt.Println(<span class="hljs-string">"Total execution time: "</span>, time.Since(start))
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writerFunction</span><span class="hljs-params">(wg *sync.WaitGroup, m *sync.RWMutex)</span></span> {
    <span class="hljs-keyword">defer</span> wg.Done()
    m.Lock()
    m.Unlock()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">readerFunction</span><span class="hljs-params">(wg *sync.WaitGroup, m *sync.RWMutex)</span></span> {
    <span class="hljs-keyword">defer</span> wg.Done()
    m.RLock()
    time.Sleep(<span class="hljs-number">1</span> * time.Second)
    m.RUnlock()
}
</code></pre>
<pre><code class="lang-bash">➜  go go run main.go
Total execution time:  1.0011145s
</code></pre>
<p><a target="_blank" href="https://goplay.tools/snippet/jIVoKdkdoyD">Run this code in Go Playground</a></p>
<p>The above program uses RWMutex for synchronisation and it takes <code>1.0011145s</code> to execute.</p>
<p>The difference is the execution time is quite significant.</p>
<p>It is important to use RWMutex judiciously because it may not be appropriate for all types of shared resources. For example, if the shared resource is small and is accessed frequently, the overhead of acquiring and releasing locks may outweigh the benefits of using RWMutex. In such cases, other synchronization mechanisms like atomic operations or channels may be more appropriate.</p>
<p><em>In the next blog, we'll look into</em> <strong><em>cond, once and pool</em></strong> <em>primitives provided by the sync package.</em></p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Concurrency in Go (Part-1): Goroutines, Channels and Select]]></title><description><![CDATA[Introduction
Concurrency, asynchronous, parallel and threaded are some keywords we see floating around when we talk about running multiple processes using multiple resources. Although these terms may appear interchangeable in English, they have disti...]]></description><link>https://pratikjagrut.space/concurrency-in-go-part-1-goroutines-channels-and-select</link><guid isPermaLink="true">https://pratikjagrut.space/concurrency-in-go-part-1-goroutines-channels-and-select</guid><category><![CDATA[Go Language]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[goroutines]]></category><category><![CDATA[concurrency-in-go]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Wed, 15 Mar 2023 13:08:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/o0HrQE7bNHM/upload/e2f0abd01045a5e0779996b4ed4c076f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Concurrency, asynchronous, parallel and threaded are some keywords we see floating around when we talk about running multiple processes using multiple resources. Although these terms may appear interchangeable in English, they have distinct differences in computer language, particularly at the compiler level and during runtime execution, as well as in their underlying philosophies.</p>
<p>In the software development world, in theory, concurrency and parallelism are considered the same and used interchangeably though they aren't the same. They may have some overlapping similarities but still, they're different. <strong><em>Concurrency is dealing with a lot of things at once and parallelism is doing a lot of things at once</em></strong>.</p>
<p>Concurrency is at the code level, it is a way of structuring the code so that it may use parallelism to run but not necessarily. We can not write parallel code we can only write concurrent code hoping it will run parallel.</p>
<p>For example, if you write a chat application then it needs to be able to handle each message from each user independently without affecting other users. So you structure your program in such a way that employs concurrency. Now suppose you've got a single-core CPU, in this case, the second message will have to wait until the first message is processed but if you have core CPUs then both messages will be processed parallelly.</p>
<h3 id="heading-gos-philosophy-of-concurrency">Go's philosophy of concurrency</h3>
<p>It is very important to understand the thought behind Go's pattern of achieving concurrency before we begin to write concurrent code.</p>
<p>Go is a concurrent language. Concurrency primitives are built in Go's core, so it implicitly supports concurrency. Go was designed around CSP. CSP stands for <strong><em>Communicating Sequential Processes</em></strong>. It was introduced by <strong><em>Charles Antony Richard Hoare</em></strong> in 1978 in a paper published by the same name at the Association for Computing Machinery(ACM).</p>
<h3 id="heading-communicating-sequential-processes">Communicating Sequential Processes</h3>
<p>CSP works on three simple rules:</p>
<ul>
<li><h4 id="heading-write-sequential-code">Write sequential code</h4>
<p>  Writing parallel code is not an easy task. We've to use a significant amount of brain power to understand the problem and write in a way that it'll surely run in parallel without getting into any parallel processes running traps such as deadlock or livelock. Instead writing sequential code is easy. We've been doing it all the time.</p>
</li>
<li><h4 id="heading-processes-will-have-local-state-and-no-shared-state">Processes will have local state and no shared state</h4>
<p>  One of Go's mottos is, <strong><em>Share memory by communicating, don't communicate by sharing memory</em></strong>. So every process will have its local state and no shared state but if the process has to share data with another process then communicate that data instead of using shared memory. This means a process will send a copy of data to another process.</p>
</li>
<li><h4 id="heading-scale-by-adding-the-same-processes">Scale by adding the same processes</h4>
<p>  So once you have a sequential code that can be run independently, then add more of those processes to scale your software.</p>
</li>
</ul>
<p>Go is primarily designed around these CSP primitives but it also supports the traditional way of writing concurrent code using <strong><em>Memory Access Synchronization</em></strong>.</p>
<h3 id="heading-concurrency-building-blocks-in-go">Concurrency building blocks in Go</h3>
<p>To write a concurrent program, Go provides us with a toolset:</p>
<ul>
<li><p>Goroutines</p>
</li>
<li><p>Channels</p>
</li>
<li><p>Select</p>
</li>
<li><p>Sync package</p>
</li>
</ul>
<h3 id="heading-goroutines">Goroutines</h3>
<p>Go follows a concurrency model called <code>fork-join</code><strong><em>.</em></strong> Fork-join means that a program can create a separate branch of execution, or child process, that runs concurrently with its parent process and will eventually rejoin the parent process at a later point in time.</p>
<p>In Go, this forked process or child process can be called a goroutine.</p>
<p>Goroutines are unique to Go. It is one of the basic units of the Go program. It is a lightweight thread of execution that enables concurrent programming.</p>
<p>Goroutines are neither the OS thread nor the green thread, they're abstraction over coroutines. Coroutines are concurrent subroutines that can not be interrupted, they can be suspended or reentered through multiple points in execution. Goroutines are lightweight, cheap and faster at execution than thread.</p>
<p>Every Go program has at least one Goroutine, i.e <code>main goroutine</code><strong><em>.</em></strong></p>
<p><code>go</code> keyword is used to fork a child i.e to create a goroutine in the program.</p>
<p>Here's an example of a goroutine:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"net/http"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchURL</span><span class="hljs-params">(url <span class="hljs-keyword">string</span>)</span></span> {
    resp, err := http.Get(url)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        fmt.Println(<span class="hljs-string">"Error:"</span>, err)
        <span class="hljs-keyword">return</span>
    }
    fmt.Println(<span class="hljs-string">"URL hit: "</span>, url)
    <span class="hljs-keyword">defer</span> resp.Body.Close()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    urls := []<span class="hljs-keyword">string</span>{
        <span class="hljs-string">"https://www.google.com"</span>,
        <span class="hljs-string">"https://www.youtube.com"</span>,
        <span class="hljs-string">"https://www.amazon.com"</span>,
        <span class="hljs-string">"https://www.linkedin.com"</span>,    
    }

    <span class="hljs-keyword">for</span> _, url := <span class="hljs-keyword">range</span> urls {
        <span class="hljs-keyword">go</span> fetchURL(url)
    }
    time.Sleep(<span class="hljs-number">2</span> * time.Second)
}
</code></pre>
<p>If you run the above program you'll see the output as follows.</p>
<pre><code class="lang-bash">➜ go run main.go
URL hit:  https://www.youtube.com
URL hit:  https://www.google.com
URL hit:  https://www.linkedin.com
URL hit:  https://www.amazon.com
</code></pre>
<p>A <strong><em>function</em></strong> called with a <code>go</code> keyword, that's all we need to create a block of code that runs concurrently. This is how the first rule of CSP is satisfied, write a sequential process that is capable of running independently.</p>
<p>In the above example, we're creating a goroutine for each URL. <code>time.Sleep()</code> is used to block the <code>main goroutine</code> until all the goroutines are finished execution. Go provides better features, such as <code>channels</code> and <code>sync package</code> to block or to make the parent process wait for goroutines.</p>
<h3 id="heading-channels">Channels</h3>
<p>Channels in Go are synchronization primitives of CSP. Channels are widely used for communicating data between goroutines.</p>
<p>Channels can be thought of as a river. Similarly how river functions, a channel functions, as a means of conveying a continuous flow of information. They're typed conduits through which goroutines can safely and efficiently send and receive data.</p>
<p>Creating a channel is very easy. You've to declare a chan variable with the datatype.</p>
<p>Here's an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> chanName <span class="hljs-keyword">chan</span> <span class="hljs-keyword">interface</span>{}
chaneName := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">interface</span>{})
</code></pre>
<p>The above example of creating a bidirectional channel, i.e. we can write to or read from the channel but Go also allows us to create a unidirectional channel.</p>
<p>To create a unidirectional channel we need to use the <code>&lt;-</code> operator. The position of the <code>&lt;-</code> operator decides if the channel is a read channel or a write channel.</p>
<p>Here's an example of a read-only channel that can receive values of the <code>interface{}</code> type.</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> chanName &lt;-<span class="hljs-keyword">chan</span> <span class="hljs-keyword">interface</span>{}
chaneName := <span class="hljs-built_in">make</span>(&lt;-<span class="hljs-keyword">chan</span> <span class="hljs-keyword">interface</span>{})
</code></pre>
<p>Here's an example of a write-only channel that can send values of the <code>interface{}</code> type.</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> chanName <span class="hljs-keyword">chan</span>&lt;- <span class="hljs-keyword">interface</span>{}
chaneName := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span>&lt;- <span class="hljs-keyword">interface</span>{})
</code></pre>
<p>Unidirectional channels are not often instantiated instead, they're used as parameters and return types of functions.</p>
<p>Here's an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"net/http"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchURL</span><span class="hljs-params">(url <span class="hljs-keyword">string</span>, done <span class="hljs-keyword">chan</span>&lt;- <span class="hljs-keyword">bool</span>)</span></span> {
    resp, err := http.Get(url)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        fmt.Println(<span class="hljs-string">"Error:"</span>, err)
        <span class="hljs-keyword">return</span>
    }
    fmt.Println(<span class="hljs-string">"URL hit: "</span>, url)
    <span class="hljs-keyword">defer</span> resp.Body.Close()
    done &lt;- <span class="hljs-literal">true</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    urls := []<span class="hljs-keyword">string</span>{
        <span class="hljs-string">"https://www.google.com"</span>,
        <span class="hljs-string">"https://www.youtube.com"</span>,
        <span class="hljs-string">"https://www.amazon.com"</span>,
        <span class="hljs-string">"https://www.linkedin.com"</span>,
    }
    <span class="hljs-comment">// Create a boolean channel</span>
    done := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">bool</span>)
    <span class="hljs-comment">// Close channel after use</span>
    <span class="hljs-keyword">defer</span> <span class="hljs-built_in">close</span>(done)
    <span class="hljs-comment">// Create goroutines</span>
    <span class="hljs-keyword">for</span> _, url := <span class="hljs-keyword">range</span> urls {
        <span class="hljs-keyword">go</span> fetchURL(url, done)
    }
    <span class="hljs-comment">// Block the main goroutine execution</span>
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">len</span>(urls); i++ {
        &lt;-done
    }
}
</code></pre>
<p>This is the same example from the goroutine section. Here we used channels to block the execution of the main goroutine. Channel done is declared as a bidirectional channel in the main but we passed it as a unidirectional channel (only send/write). Go implicitly converted the bidirectional channel to a unidirectional channel.</p>
<p>Method <code>close()</code> is used to close the channel after use. When a closed channel is written to, a panic occurs.</p>
<pre><code class="lang-bash">panic: send on closed channel
</code></pre>
<p>Closing a channel is not strictly necessary, and there are situations where it is not needed. However, it is a good practice to close channels when they are no longer needed, as it allows the receiving goroutines to exit gracefully and can prevent memory leaks.</p>
<h4 id="heading-buffered-channel">Buffered channel</h4>
<p>In Go, a buffered channel is a channel with a fixed capacity that allows multiple values of data to be stored. Buffered channels allow us to make <strong><em>n</em></strong> writes, where n is capacity defined, regardless of whether it's being read or not. We can create a buffered channel by passing capacity in <strong><em>integer</em></strong> value to make a function. A buffered channel is an in-memory FIFO queue for concurrent processes to communicate.</p>
<p>Here's an example of a buffered channel:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"net/http"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchURL</span><span class="hljs-params">(urls []<span class="hljs-keyword">string</span>, done <span class="hljs-keyword">chan</span>&lt;- <span class="hljs-keyword">string</span>)</span></span> {
    <span class="hljs-keyword">for</span> _, url := <span class="hljs-keyword">range</span> urls {
        resp, err := http.Get(url)
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            fmt.Println(<span class="hljs-string">"Error:"</span>, err)
            <span class="hljs-keyword">return</span>
        }
        <span class="hljs-keyword">defer</span> resp.Body.Close()
        done &lt;- fmt.Sprintln(<span class="hljs-string">"URL hit: "</span>, url)
    }
    <span class="hljs-built_in">close</span>(done)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    urls := []<span class="hljs-keyword">string</span>{
        <span class="hljs-string">"https://www.google.com"</span>,
        <span class="hljs-string">"https://www.youtube.com"</span>,
        <span class="hljs-string">"https://www.amazon.com"</span>,
        <span class="hljs-string">"https://www.linkedin.com"</span>,
    }
    done := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>, <span class="hljs-built_in">len</span>(urls))
    <span class="hljs-keyword">go</span> fetchURL(urls, done)

    <span class="hljs-keyword">for</span> v := <span class="hljs-keyword">range</span> done {
        fmt.Println(v)
    }
}
</code></pre>
<p>In the above example, we created a buffered channel of type string and capacity equal to the length of the slice, in this case, 4. We can use <code>range</code> to fetch the data from the buffered channel. The important thing to notice is that when we use range to fetch data the buffered channel has to be closed once data is populated otherwise for loop will keep on waiting forever.</p>
<h3 id="heading-select-statement">Select statement</h3>
<p>In Go, the select statement is like a switch statement but for channels. It's one of the important features of Go's concurrency. It is used to choose from multiple channel operations that are waiting for information to be sent or received on a particular channel.</p>
<p>Here's a code block showing how to use a select statement.</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> c1, c2 &lt;-<span class="hljs-keyword">chan</span> <span class="hljs-keyword">int</span>
<span class="hljs-keyword">select</span> {
<span class="hljs-keyword">case</span> &lt;- c1:
    <span class="hljs-comment">// Do something</span>
<span class="hljs-keyword">case</span> &lt;- c2:
    <span class="hljs-comment">// Do something</span>
<span class="hljs-keyword">case</span> &lt;-time.After(<span class="hljs-number">2</span> * time.Second):
        fmt.Println(<span class="hljs-string">"Timed out."</span>)
        <span class="hljs-keyword">return</span>
<span class="hljs-keyword">default</span>:
    <span class="hljs-comment">// Do someting until all channels are blocked</span>
}
</code></pre>
<p>Even though the select statement looks like a switch statement but its execution is very different. Cases in the select statement do not execute sequentially, instead, all channels are considered simultaneously to check if any of them is ready. If none of the channels is ready then the default block is executed over and over again.</p>
<p>Here's an example of the select statement:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"net/http"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchURL</span><span class="hljs-params">(url <span class="hljs-keyword">string</span>, urlChan <span class="hljs-keyword">chan</span>&lt;- <span class="hljs-keyword">string</span>)</span></span> {
    resp, err := http.Get(url)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        fmt.Println(<span class="hljs-string">"Error:"</span>, err)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-keyword">defer</span> resp.Body.Close()
    urlChan &lt;- fmt.Sprintln(<span class="hljs-string">"URL hit first: "</span>, url)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    urls := []<span class="hljs-keyword">string</span>{
        <span class="hljs-string">"https://www.google.com"</span>,
        <span class="hljs-string">"https://www.youtube.com"</span>,
    }

    googleChan := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)
    youtubeChan := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)

    channels := []<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>{googleChan, youtubeChan}

    <span class="hljs-keyword">for</span> i, url := <span class="hljs-keyword">range</span> urls {
        <span class="hljs-keyword">go</span> fetchURL(url, channels[i])
    }

    <span class="hljs-keyword">select</span> {
    <span class="hljs-keyword">case</span> msg := &lt;-googleChan:
        fmt.Println(msg)
    <span class="hljs-keyword">case</span> msg := &lt;-youtubeChan:
        fmt.Println(msg)
    }
}
</code></pre>
<p>In the above program, we're trying to hit URLs and then using select to block the execution of the main goroutine. Whichever channel is ready that case will be executed.</p>
<pre><code class="lang-bash">➜  go run main.go
URL hit first:  https://www.youtube.com
</code></pre>
<p>We can use an infinite for loop to keep on waiting for all channels to be ready or till time out.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"net/http"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchURL</span><span class="hljs-params">(url <span class="hljs-keyword">string</span>, urlChan <span class="hljs-keyword">chan</span>&lt;- <span class="hljs-keyword">string</span>)</span></span> {
    resp, err := http.Get(url)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        fmt.Println(<span class="hljs-string">"Error:"</span>, err)
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-keyword">defer</span> resp.Body.Close()
    urlChan &lt;- fmt.Sprintln(<span class="hljs-string">"URL hit: "</span>, url)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    urls := []<span class="hljs-keyword">string</span>{
        <span class="hljs-string">"https://www.google.com"</span>,
        <span class="hljs-string">"https://www.youtube.com"</span>,
        <span class="hljs-string">"https://www.amazon.com"</span>,
        <span class="hljs-string">"https://www.linkedin.com"</span>,
    }

    googleChan := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)
    youtubeChan := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)
    amazonChan := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)
    linkedinChan := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>)

    channels := []<span class="hljs-keyword">chan</span> <span class="hljs-keyword">string</span>{
        googleChan,
        youtubeChan,
        amazonChan,
        linkedinChan,
    }

    <span class="hljs-keyword">for</span> i, url := <span class="hljs-keyword">range</span> urls {
        <span class="hljs-keyword">go</span> fetchURL(url, channels[i])
    }

    <span class="hljs-keyword">for</span> {
        <span class="hljs-keyword">select</span> {
        <span class="hljs-keyword">case</span> url := &lt;-googleChan:
            fmt.Println(url)
        <span class="hljs-keyword">case</span> url := &lt;-youtubeChan:
            fmt.Println(url)
        <span class="hljs-keyword">case</span> url := &lt;-amazonChan:
            fmt.Println(url)
        <span class="hljs-keyword">case</span> url := &lt;-linkedinChan:
            fmt.Println(url)
        <span class="hljs-keyword">case</span> &lt;-time.After(<span class="hljs-number">2</span> * time.Second):
            fmt.Println(<span class="hljs-string">"Timed out."</span>)
            <span class="hljs-keyword">return</span>
        }
    }
}
</code></pre>
<pre><code class="lang-bash">➜ go run main.go
URL hit:  https://www.youtube.com
URL hit:  https://www.linkedin.com
URL hit:  https://www.google.com
URL hit:  https://www.amazon.com
Timed out.
</code></pre>
<h3 id="heading-sync-package">Sync package</h3>
<p>In addition to using channels, Go also allows for the more traditional approach of writing concurrent programs that utilize memory access synchronization. The <code>sync</code> package offers various primitives, including <code>WaitGroup</code>, <code>Mutex</code>, <code>RWMutex</code>, <code>Cond</code>, <code>Once</code>, and <code>Pool</code>.</p>
<p><code>We will explore the sync package in greater detail in a separate blog post.</code></p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
<p><strong><em>Reference: "Concurrency in Go: Tools and Techniques for Developers" by Katherine Cox-Buday</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Git Aliases]]></title><description><![CDATA[Git is the most widely used Version Control System (VCS) or Source Code Management(SCM) software. It is a day-to-day go-to tool for many developers. Many developers use a terminal/command line to operate it.
In the terminal, we type git commands git ...]]></description><link>https://pratikjagrut.space/git-aliases</link><guid isPermaLink="true">https://pratikjagrut.space/git-aliases</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[aliases]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Developer Tools]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Fri, 02 Dec 2022 22:55:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UT8LMo-wlyk/upload/7c3d586a09a3a012f364b82ea89841d2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><code>Git</code> is the most widely used <code>Version Control System (VCS)</code> or <code>Source Code Management(SCM)</code> software. It is a day-to-day go-to tool for many developers. Many developers use a terminal/command line to operate it.</p>
<p>In the terminal, we type git commands <code>git &lt;sub-command&gt; &lt;flag&gt;</code> it runs if it succeeds we're happy. On a day-to-day basis, we mostly use repetitive commands like <code>git pull &lt;remote&gt; &lt;branch&gt;</code>, <code>git push &lt;remote&gt; &lt;branch&gt;</code>, <code>git commit</code> and many others and sometimes we use prolonged commands like this one <code>git log --graph --pretty=format:'%Cred%h%Creset %Cgreen%cr%Creset -%C(yellow)%d%Creset %s %C(bold blue)[%cn]%Creset' --abbrev-commit --date=relative</code> which prints commit history in a custom fashion.</p>
<p>Typing those repetitive or lengthy, complex commands with too many arguments could be erroneous and could decrease our efficiency ensuing less productivity.</p>
<p>In this article, we'll learn how to run Git commands efficiently and develop a more productive Git workflow using Aliases.</p>
<p><strong><em>NOTE: The aliases in this article are my personal choice influenced by my day-to-day Git interaction.</em></strong></p>
<h2 id="heading-what-is-an-alias">What is an alias?</h2>
<p>Aliases are short commands assigned to a particular command. It can be visualized as a shortcut for any command.</p>
<p>Creating an alias serves some basic needs:</p>
<ul>
<li><p>It helps to shorten the lengthy command and saves us from tedious, erroneous typing.</p>
</li>
<li><p>It saves us from memorizing complex commands.</p>
</li>
<li><p>Creates abridged commands for regularly used commands ensuing in an increase in productivity.</p>
</li>
</ul>
<p><strong><em>We can use two types of aliases for Git commands:</em></strong></p>
<ul>
<li><p>Bash alias</p>
</li>
<li><p>Git alias</p>
</li>
</ul>
<p>We'll look into both.</p>
<h2 id="heading-bash-alias">Bash Alias</h2>
<p>Defining a bash alias is a simple task. Below is a command for it.</p>
<pre><code class="lang-go">alias g=<span class="hljs-string">'git'</span>
</code></pre>
<p>And done, we've <code>g</code> as an alias for the <code>git</code> command.</p>
<p>But this alias is not persistent as soon as you end the terminal session the alias is gone. To make it persistent we've to add this alias in <code>.bashrc</code> if you use the bash shell or <code>.zshrc</code> if you use zsh. These files are mostly located in your home directory.</p>
<p>To know what shell you're using type echo</p>
<pre><code class="lang-go">echo <span class="hljs-string">"$SHELL"</span>
/usr/bin/zsh
</code></pre>
<p>For the git command, I've two bash aliases <code>g</code> and <code>gt</code>. Sometimes due to an old habit, I tend to type <code>git</code> instead of <code>g</code> and while doing that sometimes I miss the <code>i</code> in <code>git</code> so to avoid throwing an error I added <code>gt</code> as an alias in <code>.zshrc</code>.</p>
<pre><code class="lang-go">alias g=<span class="hljs-string">'git'</span>
alias gt=<span class="hljs-string">'git'</span>
</code></pre>
<h2 id="heading-git-alias">Git alias</h2>
<p>To define a git alias we use the <code>git config</code> command. We can define two types of aliases in Git.</p>
<ul>
<li><p><code>Global aliases</code>, are stored in <code>.gitconfig</code> file which is mainly located in the home directory. These aliases are available to all git repositories present in the system. Command to define global alias:</p>
<pre><code class="lang-go">  git config --global alias.&lt;alias_name&gt; <span class="hljs-string">'&lt;command&gt;'</span>
</code></pre>
<pre><code class="lang-go">  or you can directly edit the .gitconfig file.
</code></pre>
</li>
<li><p><code>Local aliases</code>, which are stored in <code>.git/config</code> file of the particular project. These aliases are not available to any other repository. Command to define local alias:</p>
<pre><code class="lang-go">  git config alias.&lt;alias_name&gt; <span class="hljs-string">'&lt;command&gt;'</span>
</code></pre>
<pre><code class="lang-go">  or you can directly edit the .git/config file.
</code></pre>
</li>
</ul>
<h3 id="heading-some-useful-git-aliases">Some useful git aliases</h3>
<ul>
<li><h4 id="heading-git-status">Git Status</h4>
<p>  <code>git status</code> is a command which is used very frequently to see changed or untracked files.</p>
<pre><code class="lang-go">  git config --global alias.st <span class="hljs-string">'status'</span>
</code></pre>
<p>  So now instead of <code>git status</code> we can just type <code>git st</code> or <code>g st</code> if bash alias <code>g=git</code> is set. This is the benefit of using aliases, the whole command can be converted into a few characters.</p>
<pre><code class="lang-go">  $ g st
  On branch master
  Your branch is up to date with <span class="hljs-string">'origin/master'</span>.

  nothing to commit, working tree clean
</code></pre>
<p>  The git will store this alias in <code>.gitconfig</code> file under <code>[alias]</code> section as <code>st = status</code>.</p>
</li>
<li><h4 id="heading-git-pull">Git Pull</h4>
<p>  <code>git pull &lt;remote&gt; &lt;ref/branch&gt;</code> this command pulls the code from a specified remote branch.</p>
<pre><code class="lang-go">  git config --global alias.pl <span class="hljs-string">'pull'</span>
</code></pre>
<p>  Now the pull command will be <code>git pl &lt;remote&gt; &lt;ref/branch&gt;</code>.</p>
<p>  We can shorten it further depending on the remote and branch.</p>
<pre><code class="lang-go">  git config --global alias.plo <span class="hljs-string">'pull origin'</span>
</code></pre>
<p>  Now the command <code>git plo main</code> is the same as <code>git pull origin main</code>.</p>
<p>  We can create dedicated alias for <code>git pull origin main</code></p>
<pre><code class="lang-go">  git config --global alias.plom <span class="hljs-string">'pull origin main'</span>
</code></pre>
<p>  Now the entire command is abridged, <code>git plom</code>.</p>
</li>
<li><h4 id="heading-git-checkout">Git Checkout</h4>
<p>  <code>git checkout</code> Switch branches or restore working tree files.</p>
<pre><code class="lang-go">  git config --global alias.co <span class="hljs-string">'checkout'</span>
</code></pre>
<p>  Now we can use <code>git co &lt;branch&gt;</code> to checkout that branch.</p>
<p>  To create a new branch we use <code>git checkout -b &lt;new_branch&gt; &lt;start_point&gt;</code></p>
<pre><code class="lang-go">  git config --global alias.cnb <span class="hljs-string">'checkout -b'</span>
</code></pre>
<p>  So now we can use <code>git cnb &lt;new_branch&gt; &lt;start_point&gt;</code></p>
</li>
<li><h4 id="heading-git-branch">Git Branch</h4>
<p>  <code>git branch</code> List, create or delete branches</p>
<pre><code class="lang-go">  git config --global alias.br <span class="hljs-string">'branch'</span>
</code></pre>
<pre><code class="lang-go">  $ git br

  * branch1
  main
</code></pre>
</li>
<li><h4 id="heading-git-add">Git add</h4>
<p>  <code>git add &lt;pathspec&gt;...</code> adds file contents to the index</p>
<pre><code class="lang-go">  git config --global alias.a <span class="hljs-string">'add'</span>
</code></pre>
<p>  The command will be <code>git a &lt;pathspec&gt;...</code></p>
<p>  To add all the files (changed + untracked) we can do <code>git add .</code></p>
<pre><code class="lang-go">  git config --global alias.aa <span class="hljs-string">'add .'</span>
</code></pre>
<p>  Now to add all files we can use <code>git aa</code></p>
</li>
<li><h4 id="heading-git-commit">Git commit</h4>
<p>  After adding files to the index we use <code>git commit</code> to record changes to the repository. For git commit alias could be:</p>
<pre><code class="lang-go">  git config --global alias.ci <span class="hljs-string">'commit'</span>
</code></pre>
<pre><code class="lang-sh">  $ git ci

  [update.theme 89f083e] Update CR yaml
  1 file changed, 1 insertion(+)
  create mode 100644 cr.yaml
</code></pre>
</li>
<li><h4 id="heading-git-push">Git push</h4>
<p>  Once your changes are committed and you need to update the remote reference with new changes we use <code>git push &lt;remote&gt; &lt;branch&gt;</code></p>
<pre><code class="lang-go">  git config --global alias.p <span class="hljs-string">'push'</span>
</code></pre>
<p>  We can shorten it further depending on the remote and branch.</p>
<pre><code class="lang-go">  git config --global alias.po <span class="hljs-string">'push origin'</span>
</code></pre>
<p>  Now the command <code>git po main</code> is the same as <code>git push origin main</code>.</p>
<p>  We can create dedicated alias for <code>git push origin main</code></p>
<pre><code class="lang-go">  git config --global alias.pom <span class="hljs-string">'push origin main'</span>
</code></pre>
<p>  Now the entire command is abridged, <code>git pom</code>.</p>
</li>
<li><h4 id="heading-git-log">Git log</h4>
<p>  <code>git log</code> is one of the most important commands in git. It shows us the commit history. Now there are various ways of seeing commit history, depending on how we wanna see commit history we can use the flags.</p>
<p>  I usually use these three aliases for logs.</p>
<p>  This alias shows complete commit logs with the addition and deletion stats.</p>
<pre><code class="lang-go">  git config --global alias.lg <span class="hljs-string">'log --stat'</span>
</code></pre>
<pre><code class="lang-go">  $ git lg

  commit <span class="hljs-number">8</span>b6ac3a9789002a2c578139c830f17b9e18b53f7 (HEAD -&gt; git.aliases, origin/main, origin/HEAD, update.theme)
  Author: Pratik Jagrut &lt;<span class="hljs-number">26519653</span>+pratikjagrut@users.noreply.github.com&gt;
  Date:   Sat May <span class="hljs-number">1</span> <span class="hljs-number">21</span>:<span class="hljs-number">47</span>:<span class="hljs-number">48</span> <span class="hljs-number">2021</span> +<span class="hljs-number">0530</span>

      Update public directory

  public | <span class="hljs-number">2</span> +-
  <span class="hljs-number">1</span> file changed, <span class="hljs-number">1</span> insertion(+), <span class="hljs-number">1</span> deletion(-)
</code></pre>
<p>  This alias draws a text-based graphical representation of the commit history printed in between commits with relative time.</p>
<pre><code class="lang-go">  git config --global alias.lgdr <span class="hljs-string">"log --graph --pretty=format:'%Cred%h%Creset %Cgreen%cr%Creset -%C(yellow)%d%Creset %s %C(bold blue)[%cn]%Creset' --abbrev-commit --date=relative"</span>
</code></pre>
<pre><code class="lang-go">  $ git lgdr

  * <span class="hljs-number">8</span>b6ac3a <span class="hljs-number">6</span> hours ago - (HEAD -&gt; git.aliases, origin/main, origin/HEAD, update.theme) Update public directory [Pratik Jagrut]
  * f47c1c6 <span class="hljs-number">6</span> hours ago - Update theme [Pratik Jagrut]
</code></pre>
<p>  This alias draws a text-based graphical representation of the commit history printed in between commits with a short format of the date.</p>
<pre><code class="lang-go">  git config --global alias.lgds <span class="hljs-string">"log --graph --pretty=format:'%Cred%h%Creset %Cgreen%cr%Creset -%C(yellow)%d%Creset %s %C(bold blue)[%cn]%Creset' --abbrev-commit --date=short</span>
</code></pre>
<pre><code class="lang-go">  $ git lgds

  * <span class="hljs-number">8</span>b6ac3a <span class="hljs-number">2021</span><span class="hljs-number">-05</span><span class="hljs-number">-01</span> - (HEAD -&gt; git.aliases, origin/main, origin/HEAD, update.theme) Update public directory [Pratik Jagrut]
  * f47c1c6 <span class="hljs-number">2021</span><span class="hljs-number">-05</span><span class="hljs-number">-01</span> - Update theme [Pratik Jagrut]
</code></pre>
</li>
</ul>
<p><strong><em>Here's the .gitconfig file for all the above aliases.</em></strong></p>
<pre><code class="lang-go">[alias]
  st = status
  pl = pull
  plo = pull origin
  plom = pull origin main
  co = checkout
  cnb = checkout -b
  br = branch
  a = add
  aa = add .
  ci = commit
  p = push
  po = push origin
  pom = push origin main
  lg = log --stat
  lgdr = log --graph --pretty=format:<span class="hljs-string">'%Cred%h%Creset %Cgreen%cr%Creset -%C(yellow)%d%Creset %s %C(bold blue)[%cn]%Creset'</span> --abbrev-commit --date=relative
  lgds = log --graph --pretty=format:<span class="hljs-string">'%Cred%h%Creset %Cgreen%cd%Creset -%C(yellow)%d%Creset %s %C(bold blue)[%cn]%Creset'</span> --abbrev-commit --date=short
</code></pre>
<p><strong><em>These were some of the aliases from my list, you can make more aliases for sub-commands like branch, remote, diff, config, etc...</em></strong></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Git aliases are a very useful feature. They help to improve the overall efficiency and productivity of the git workflow. We can define as many aliases as we want, Git is too generous. It is always good to have aliases for regularly used and lengthy commands.</p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Error Handling in Go (Part-2)]]></title><description><![CDATA[Creating errors with errors.New() function
If we don't need a custom type for an error, and we can work with a single error type then we can use errors.New() function to create an error on the fly.
Creating a new error is simple. We simply need to ca...]]></description><link>https://pratikjagrut.space/error-handling-in-go-part-2</link><guid isPermaLink="true">https://pratikjagrut.space/error-handling-in-go-part-2</guid><category><![CDATA[Go Language]]></category><category><![CDATA[error handling]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[error-handling-in-go]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Sat, 19 Nov 2022 22:45:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zlhxvIcicwk/upload/ab7e382baa91bd9db561fd6fd2bf7bcc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-creating-errors-with-errorsnew-function">Creating errors with errors.New() function</h2>
<p>If we don't need a custom type for an error, and we can work with a single error type then we can use <a target="_blank" href="https://pkg.go.dev/errors#New"><strong><em>errors.New()</em></strong></a> function to create an error on the fly.</p>
<p>Creating a new error is simple. We simply need to call the New function as shown in the below example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
  <span class="hljs-string">"errors"</span>
  <span class="hljs-string">"fmt"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">division</span><span class="hljs-params">(i, j <span class="hljs-keyword">float32</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  <span class="hljs-keyword">if</span> j == <span class="hljs-number">0</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>, errors.New(<span class="hljs-string">"ERROR: Division by Zero"</span>)
  }
  <span class="hljs-keyword">return</span> i / j, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  <span class="hljs-keyword">if</span> _, err := division(<span class="hljs-number">157</span>, <span class="hljs-number">0</span>); err != <span class="hljs-literal">nil</span> {
    fmt.Println(err)
  }
}
</code></pre>
<pre><code class="lang-go">ERROR: Division by Zero
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/BYKrriQfXUh"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p><strong><em>NOTE: Each call to the New() function returns a distinct error value even if the text is identical.</em></strong></p>
<p><strong><em>The New() function makes it easy to create an error, but how New() function is doing this?</em></strong></p>
<p>Take a look at the source code of the <a target="_blank" href="https://github.com/golang/go/blob/master/src/errors/errors.go"><strong><em>errors package.</em></strong></a></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> errors

<span class="hljs-comment">// New returns an error that formats as the given text.</span>
<span class="hljs-comment">// Each call to New returns a distinct error value even if the text is identical.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">New</span><span class="hljs-params">(text <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">error</span></span> {
  <span class="hljs-keyword">return</span> &amp;errorString{text}
}

<span class="hljs-comment">// errorString is a trivial implementation of error.</span>
<span class="hljs-keyword">type</span> errorString <span class="hljs-keyword">struct</span> {
  s <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(e *errorString)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
  <span class="hljs-keyword">return</span> e.s
}
</code></pre>
<p>The New () function takes a string as input and returns the pointer to the type <code>errorString</code> struct that only has one field <code>s string</code>.</p>
<p>The return type of the New() function is <code>error</code>, and the actual returning value is a pointer to the <code>errorString</code> struct. This means type <code>errorString</code> implements <code>error interface</code>.</p>
<p>The implementation of the errors package is pretty straightforward and easy to fathom.</p>
<h2 id="heading-creating-errors-with-fmterrorf-function">Creating errors with <code>fmt.Errorf()</code> function</h2>
<p>Use of errors.New() to create new errors is just fine, but if we want to add more information or context to the error, then New() function is futile because it does not have a built-in string formatting mechanism. We will have to use something like <code>fmt.Spritnf</code> to format our error string and then pass it to the New() function which is just overwork.</p>
<p>The better way to use is <code>fmt.Errorf</code> function.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
  <span class="hljs-string">"fmt"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">division</span><span class="hljs-params">(i, j <span class="hljs-keyword">float32</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  <span class="hljs-keyword">if</span> j == <span class="hljs-number">0</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>, fmt.Errorf(<span class="hljs-string">"ERROR: Division by Zero\nDividend: %v\nDivisor: %v"</span>, i, j)
  }
  <span class="hljs-keyword">return</span> i / j, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  <span class="hljs-keyword">if</span> _, err := division(<span class="hljs-number">157</span>, <span class="hljs-number">0</span>); err != <span class="hljs-literal">nil</span> {
    fmt.Println(err)
  }
}
</code></pre>
<pre><code class="lang-go">ERROR: Division by Zero
Dividend: <span class="hljs-number">157.000000</span>
Divisor: <span class="hljs-number">0.000000</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/xmjbqIshXCi"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above program, we have replaced errors.New() function with fmt.Errorf(). Now, we can format our error and add new information to it using the Errorf function.</p>
<p>If you look at the implementation of <a target="_blank" href="https://github.com/golang/go/blob/master/src/fmt/errors.go">fmt.Errorf()</a> is a bit more complicated than the errors package due to the string formatting feature but at some level fmt.Errorf() function calls the errors.New() function.</p>
<p><strong><em>So, the common question is when to use fmt.Errorf() and errors.New()? It depends on the behaviour of the error. If the error needs to have any runtime information, like the address stored in a pointer or the time at which an error occurred, then it is a good idea to use fmt.Errorf() which gives the flexibility to format your error as per your need. On the other side, your error is more of a static behaviour or it is a sentinel error and does not need to have any runtime information, then errors.New() is good enough.</em></strong></p>
<h2 id="heading-adding-context-to-the-error">Adding context to the error</h2>
<p>Sometimes error does not make much sense unless we provide context to it. This context or additional information could be anything like the function where the error occurred or any runtime value.</p>
<p>The general way of adding context to the error is by using <code>fmt.Errorf and %v verb</code>.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
  <span class="hljs-string">"errors"</span>
  <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">var</span> ErrUnauthorizedAccess = errors.New(<span class="hljs-string">"Unauthorized access"</span>)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isUserAuthorized</span><span class="hljs-params">(uname <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">error</span></span> {
  <span class="hljs-comment">// some logic to verify user authorization</span>
  authorize := <span class="hljs-literal">false</span>
  <span class="hljs-keyword">if</span> authorize {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
  }
  <span class="hljs-keyword">return</span> ErrUnauthorizedAccess
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">searchFile</span><span class="hljs-params">(fileId <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  uname := <span class="hljs-string">"NotAnAdmin"</span>
  err := isUserAuthorized(uname)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, fmt.Errorf(<span class="hljs-string">"ERROR: searchFile: %v"</span>, err)
  }
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Return file"</span>, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  _, err := searchFile(<span class="hljs-number">10001</span>)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    fmt.Println(err)
  }
}
</code></pre>
<pre><code class="lang-go">ERROR: searchFile: Unauthorized access
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/TkD5FW9UdXF"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above example, the original error is <code>ErrUnauthorizedAccess</code> which is then annotated with extra information using <code>fmt.Errorf("ERROR: searchFile: %v", err)</code>.</p>
<p>While creating a new error using <code>fmt.Errorf</code>, everything from the original error is discarded except the text. Hence we lose the original error <code>ErrUnauthorizedAccess</code> and the only remnant of the original error is its text <code>Unauthorized access</code>. The below example illustrates this problem:</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  _, err := searchFile(<span class="hljs-number">10001</span>)
  <span class="hljs-keyword">if</span> err == ErrUnauthorizedAccess {
    fmt.Println(<span class="hljs-string">"Please use the valid authorization token"</span>)
  }
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/zxoZn0eLwU2"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above snippet, the error returned from fmt.Errorf is compared to the original error which should be completely valid. But if you run this code, you will see the blank output. This is because the new error has lost the original error and capability to compare it.</p>
<p>To avoid such situations, we can create a custom error type that stores the original error.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
  <span class="hljs-string">"errors"</span>
  <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">var</span> ErrUnauthorizedAccess = errors.New(<span class="hljs-string">"Unauthorized access"</span>)

<span class="hljs-keyword">type</span> serviceError <span class="hljs-keyword">struct</span> {
  fn  <span class="hljs-keyword">string</span>
  err error
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(e *serviceError)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
  <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Error: %v: %v"</span>, e.fn, e.err)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isUserAuthorized</span><span class="hljs-params">(uname <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">error</span></span> {
  <span class="hljs-comment">// some logic to verify user authorization</span>
  authorize := <span class="hljs-literal">false</span>
  <span class="hljs-keyword">if</span> authorize {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
  }
  <span class="hljs-keyword">return</span> ErrUnauthorizedAccess
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">searchFile</span><span class="hljs-params">(fileId <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  uname := <span class="hljs-string">"NotAnAdmin"</span>
  err := isUserAuthorized(uname)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, &amp;serviceError{fn: <span class="hljs-string">"searchFile"</span>, err: err}
  }
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Return file"</span>, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  _, err := searchFile(<span class="hljs-number">10001</span>)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">if</span> errVal, ok := err.(*serviceError); ok &amp;&amp; errVal.err == ErrUnauthorizedAccess{
        fmt.Println(<span class="hljs-string">"Please use the valid authorization token"</span>)
    }
  }
}
</code></pre>
<pre><code class="lang-go">Please use a valid authorization token
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/Wsv_szFqW6H"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above program, we've struct <code>serviceError</code>, a custom error type that stores the original error in the <code>err</code> field, and <code>fn</code> field that stores the function name where the error will occur(i.e context of an error). In the main function, we're using type assertion to extract the concrete value of <code>err</code> and using it to compare with the original error.</p>
<p><strong><em>This block of code is also referred to as the unwrapping of error. Because we're extracting the underlying error.</em></strong></p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> errVal, ok := err.(*serviceError); ok &amp;&amp; errVal.err == ErrUnauthorizedAccess{
  fmt.Println(<span class="hljs-string">"Please use the valid authorization token"</span>)
}
</code></pre>
<h2 id="heading-wrapping-and-unwrapping-error">Wrapping and Unwrapping error</h2>
<p>Wrapping of errors means creating a hierarchy of errors by adding context or more information to the error. Consider an onion, and how each upper layer of an onion wraps around the inner layer of the onion. Similarly, one error can wrap up another error, and that error can get wrapped by another error, and so on. We can create a hierarchy of errors which is helpful to form stack trace.</p>
<p>In the above section, we've seen how we added the context to an error using fmt.Errorf is also a kind of error wrapping because it creates a new error over an original error.</p>
<p>In Go1.13, the errors package introduced some new functions to manage errors.</p>
<pre><code class="lang-go">To support wrapping, fmt.Errorf now has a %w verb <span class="hljs-keyword">for</span> creating wrapped errors, 
and three <span class="hljs-built_in">new</span> functions in the errors <span class="hljs-keyword">package</span> ( errors.Unwrap, errors.Is and errors.As) 
simplify unwrapping and inspecting wrapped errors.
</code></pre>
<p><a target="_blank" href="https://golang.org/doc/go1.13#error_wrapping"><strong><em>Read more in the release note.</em></strong></a></p>
<h4 id="heading-wrapping-error">Wrapping error</h4>
<p>When we used fmt.Errorf and %v to add context to the error we lost the original error. Since Go1.13 <code>fmt.Errorf</code> supports <code>%w</code> a verb whose argument must be an error. When %w is present fmt.Errorf wraps the error and the error is returned by fmt.Errorf will have Unwrap method that will return the argument of %w.</p>
<pre><code class="lang-go"><span class="hljs-keyword">return</span> fmt.Errorf(<span class="hljs-string">"adding more context: %w"</span>, err)
</code></pre>
<p>This wrapped error will have access to <code>errors.Is, errors.As and errors.Unwrap</code> methods which will help handle them.</p>
<h4 id="heading-errorsis">errors.Is</h4>
<p>The <code>errors.Is</code> function compares an error to a value. <code>errors.Is(err, error)</code></p>
<p>This statement</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> err == ErrUnauthorizedAccess { ... }
</code></pre>
<p>can be replaced by</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> errors.Is(err, ErrUnauthorizedAccess) { ... }
</code></pre>
<p><strong><em>In simple terms, the</em></strong> <code>error.Is</code> function behaves like a comparison to a sentinel error.</p>
<h4 id="heading-errorsas">errors.As</h4>
<p>The <code>errors.As</code> function tests whether an error is a specific type. <code>errors.As(err, &amp;e)</code></p>
<p>This statement</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> errVal, ok := err.(*Error); ok { ... }
</code></pre>
<p>can be replaced by</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> e *serviceError
<span class="hljs-keyword">if</span> errors.As(err, &amp;e) { ... }
</code></pre>
<p>err is a <code>*serviceError</code>, and e is set to the error's value</p>
<p><strong><em>In simple term,</em></strong> <code>errors.As</code> function behaves like type assertion.</p>
<h4 id="heading-errorsunwrap">errors.Unwrap</h4>
<p>Unwrap function is used to extract the underlying or wrapped error.</p>
<pre><code class="lang-go">e2 := fmt.Errorf(<span class="hljs-string">"adding more context: %w"</span>, e1)
errors.Unwrap(e2) <span class="hljs-comment">// returns e1</span>
</code></pre>
<p><strong><em>NOTE: An error containing another error may implement Unwrap method returning the underlying error. Doing so, will give access to the Is and As methods, without needing to use fmt.Errorf with %w.</em></strong></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
  <span class="hljs-string">"errors"</span>
  <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">var</span> ErrUnauthorizedAccess = errors.New(<span class="hljs-string">"Unauthorized access"</span>)

<span class="hljs-keyword">type</span> serviceError <span class="hljs-keyword">struct</span> {
  fn  <span class="hljs-keyword">string</span>
  err error
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(e *serviceError)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
  <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Error: %v: %v"</span>, e.fn, e.err)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(e *serviceError)</span> <span class="hljs-title">Unwrap</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> { <span class="hljs-keyword">return</span> e.err }

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isUserAuthorized</span><span class="hljs-params">(uname <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">error</span></span> {
  <span class="hljs-comment">// some logic to verify user authorization</span>
  authorize := <span class="hljs-literal">false</span>
  <span class="hljs-keyword">if</span> authorize {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
  }
  <span class="hljs-keyword">return</span> ErrUnauthorizedAccess
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">searchFile</span><span class="hljs-params">(fileId <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  uname := <span class="hljs-string">"NotAnAdmin"</span>
  err := isUserAuthorized(uname)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, &amp;serviceError{fn: <span class="hljs-string">"searchFile"</span>, err: err}
  }
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Return file"</span>, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  _, err := searchFile(<span class="hljs-number">10001</span>)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    fmt.Println(err)

    <span class="hljs-keyword">if</span> errors.Is(err, ErrUnauthorizedAccess) {
      fmt.Println(<span class="hljs-string">"Please use valid authorization token"</span>)
    }

    <span class="hljs-keyword">var</span> e *serviceError
    <span class="hljs-keyword">if</span> errors.As(err, &amp;e) {
      fmt.Printf(<span class="hljs-string">"Function %v returned %v error\n"</span>, e.fn, e.err)
    }

    fmt.Println(errors.Unwrap(err))
  }
}
</code></pre>
<pre><code class="lang-go">Error: searchFile: Unauthorized access
Please use a valid authorization token
Function searchFile returned Unauthorized access error
Unauthorized access
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/OJcik2q5FQk"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above program, struct <code>serviceError</code> implements the Error method, which makes it a custom error type. It has an error field and implements the <code>Unwrap</code> method which returns the original error, this lets us call <code>errors.Is</code> and <code>errors.As</code> method on it.</p>
<p>If you remember the previous example, we used this block of code to unwrap the error.</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> errVal, ok := err.(*serviceError); ok &amp;&amp; errVal.err == ErrUnauthorizedAccess{
  fmt.Println(<span class="hljs-string">"Please use the valid authorization token"</span>)
}
</code></pre>
<p>But now, we replaced it by errors.Is</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> errors.Is(err, ErrUnauthorizedAccess) {
  fmt.Println(<span class="hljs-string">"Please use valid authorization token"</span>)
}
</code></pre>
<h5 id="heading-the-same-example-using-fmterrorf-and-w-verb">The same example using fmt.Errorf and %w verb</h5>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
  <span class="hljs-string">"errors"</span>
  <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">var</span> ErrUnauthorizedAccess = errors.New(<span class="hljs-string">"Unauthorized access"</span>)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isUserAuthorized</span><span class="hljs-params">(uname <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">error</span></span> {
  <span class="hljs-comment">// some logic to verify user authorization</span>
  authorize := <span class="hljs-literal">false</span>
  <span class="hljs-keyword">if</span> authorize {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
  }
  <span class="hljs-keyword">return</span> ErrUnauthorizedAccess
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">searchFile</span><span class="hljs-params">(fileId <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  uname := <span class="hljs-string">"NotAnAdmin"</span>
  err := isUserAuthorized(uname)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, fmt.Errorf(<span class="hljs-string">"ERROR: searchFile: %w"</span>, err)
  }
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Return file"</span>, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  _, err := searchFile(<span class="hljs-number">10001</span>)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    fmt.Println(err)

    <span class="hljs-keyword">if</span> errors.Is(err, ErrUnauthorizedAccess) {
      fmt.Println(<span class="hljs-string">"Please use valid authorization token"</span>)
    }

    fmt.Println(errors.Unwrap(err))
  }
}
</code></pre>
<pre><code class="lang-go">ERROR: searchFile: Unauthorized access
Please use a valid authorization token
Unauthorized access
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/0io6Fr3Sgy1"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p><em>In software, errors are an inevitable part. We can not ignore them, thinking we'll save the hustle of handling them. But ignoring error means weakening the software instead handle it.</em></p>
<p>Below are some good reads about error handling.</p>
<ul>
<li><p><a target="_blank" href="https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully"><strong><em>Don’t just check errors, handle them gracefully</em></strong></a></p>
</li>
<li><p><a target="_blank" href="https://blog.golang.org/go1.13-errors"><strong><em>Working with Errors in Go 1.13</em></strong></a></p>
</li>
<li><p><a target="_blank" href="https://rauljordan.com/2020/07/06/why-go-error-handling-is-awesome.html"><strong><em>Why Go's Error Handling is Awesome</em></strong></a></p>
</li>
<li><p><a target="_blank" href="https://golang.org/doc/tutorial/handle-errors"><strong><em>Return and handle an error</em></strong></a></p>
</li>
</ul>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Error Handling in Go (Part-1)]]></title><description><![CDATA[Error is a result of unexpected circumstances or abnormal behaviour of the program. For example, a network connection error, a user entering incorrect data, a function invoked with inaccurate values or a file not found, and many other scenarios could...]]></description><link>https://pratikjagrut.space/error-handling-in-go-part-1</link><guid isPermaLink="true">https://pratikjagrut.space/error-handling-in-go-part-1</guid><category><![CDATA[Go Language]]></category><category><![CDATA[error handling]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[error-handling-in-go]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Fri, 11 Nov 2022 22:36:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zlhxvIcicwk/upload/ab7e382baa91bd9db561fd6fd2bf7bcc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><code>Error</code> is a result of unexpected circumstances or abnormal behaviour of the program. For example, a network connection error, a user entering incorrect data, a function invoked with inaccurate values or a file not found, and many other scenarios could cause an error. <code>Error Handling</code> is a process of knowing where an error could befall, and having a mechanism to handle it.</p>
<p>In Golang, <code>an error is a value type whose zero value is nil</code> i.e, the error is a built-in type. This coerces developers to treat the error as a <a target="_blank" href="https://en.wikipedia.org/wiki/First-class_citizen"><strong><em>first-class citizen</em></strong></a>. Errors are treated similarly as int, string, bool, etc. An error may return from any function, it may pass as a parameter, and it may store into a variable.</p>
<p>Golang has errors but no exceptions. Its way to handle the exception is not to have an exception in the first place. Please read Dave Cheney's blog about <a target="_blank" href="https://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right"><strong><em>Why Go gets exceptions right</em></strong></a>.</p>
<p>Golang has support for multiple return values from the function. This feature is primarily used for returning a result and an error. Below is a signature of a Read method from <a target="_blank" href="https://golang.org/src/bufio/bufio.go?s=4875:4925#L188"><strong><em>bufio package.</em></strong></a></p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(b *Reader)</span> <span class="hljs-title">Read</span><span class="hljs-params">(p []<span class="hljs-keyword">byte</span>)</span> <span class="hljs-params">(n <span class="hljs-keyword">int</span>, err error)</span></span>
</code></pre>
<p><code>Read</code> the method returns the number of bytes reads into p and returns a variable <code>err</code> of type <code>error</code>. So, for some reason, if this function fails, then the caller will be apprised by returning a custom-defined error. The caller should first inspect the <code>error</code> to determine if an error has occurred or not and only after that returned result should be used. Below is an idiomatic way of handling errors in Golang.</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
  <span class="hljs-comment">// handle error</span>
}
</code></pre>
<p>The above block of code is pervasive in Golang based projects. If the error value is not equal to nil that means the function has returned an error. This idiomatic way of handling errors gives us more control over error handling. We can decorate the error and make it more informative. Below is an example of error handling.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
  <span class="hljs-string">"fmt"</span>
  <span class="hljs-string">"os"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  f, err := os.Open(<span class="hljs-string">"README.md"</span>)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    fmt.Println(err)
    os.Exit(<span class="hljs-number">1</span>)
  }
  fmt.Println(f.Name(), <span class="hljs-string">"opened successfully"</span>)
}
</code></pre>
<pre><code class="lang-go">open README.md: no such file or directory
Program exited: status <span class="hljs-number">1.</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/m6f5_P8Brqz"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above program, we are trying to open the <code>README.md</code> file that is not present, so <code>os.Open</code> the function returns an error that we are inspecting and handling.</p>
<h2 id="heading-representation-of-error-type">Representation of error type</h2>
<p>In Golang, an error is a built-in type, but actually, the error is an <code>interface type made available globally</code>. <a target="_blank" href="https://golang.org/ref/spec#Errors"><strong><em>It is a single-method interface.</em></strong></a></p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> error <span class="hljs-keyword">interface</span> {
  Error() <span class="hljs-keyword">string</span>
}
</code></pre>
<p>Any type that implements the error interface is a valid error. To create a custom error, a type needs to define the <code>Error</code> method. In the above example of the opening file, the error returned from <code>os.Open</code> function was of type <a target="_blank" href="https://github.com/golang/go/blob/master/src/os/file.go#L316"><strong><em>\</em>pathError*</strong></a>. <code>pathError</code> is a custom error which <a target="_blank" href="https://golang.org/pkg/io/fs/#PathError"><strong><em>implements the error interface</em></strong></a>.</p>
<h2 id="heading-create-an-error-type">Create an error type</h2>
<p>From the above section, we know that an error is an interface, and any type which implements that interface is an error.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> httpError <span class="hljs-keyword">struct</span> {
  code   <span class="hljs-keyword">int</span>
  method <span class="hljs-keyword">string</span>
  fn     <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *httpError)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
  <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"ERROR:%d:%s:%s"</span>, h.code, h.method, h.fn)
}

<span class="hljs-comment">//Mock function to demo some operation</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getUser</span><span class="hljs-params">(uid <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  <span class="hljs-comment">// some business logic</span>
  authorized := <span class="hljs-literal">false</span>
  <span class="hljs-keyword">if</span> authorized {
    <span class="hljs-comment">//find user logic</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"User found"</span>, <span class="hljs-literal">nil</span>
  }
  <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>, &amp;httpError{code: <span class="hljs-number">401</span>, method: <span class="hljs-string">"GET"</span>, fn: <span class="hljs-string">"getUser"</span>}
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  _, err := getUser(<span class="hljs-number">1</span>)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    fmt.Println(err)
  }

  <span class="hljs-comment">// Inline variant</span>
  <span class="hljs-comment">// if _, err = getUser(2); err != nil {</span>
  <span class="hljs-comment">//  fmt.Println(err)</span>
  <span class="hljs-comment">// }</span>
}
</code></pre>
<pre><code class="lang-go">ERROR:<span class="hljs-number">401</span>:GET:getUser
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/dFSDoh2fBjz"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above example, the <code>httpError</code> struct implements the <code>error</code> interface by defining the <code>Error</code> method. <code>getUser</code> is a mock function that mocks the getUser operation.</p>
<p>Here, the main function is the caller for the methods. So the main function is supposed to handle the returned errors. In the main function, this statement <code>_, err := getUser(1)</code> executes the getUser function, stores the error in the <code>err</code> variable and ignores the result using <code>_</code>.</p>
<p>After the function call, the caller is checking if the function is returning an error or not using an if-else statement.</p>
<p>If you see the return type of an error in <code>getUser</code> function is <code>error interface type</code> but the return statement is returning a struct or say the address of the struct variable <code>&amp;httpError{code: 401, method: "GET", fn: "getUser"}</code>.</p>
<p><strong><em>If the return type of a function and the type of actual return value is different, then how can this function be returning anything?</em></strong></p>
<p>This is because the type <code>httpError</code> implements the <code>error interface</code>. Under the hood, the interface variable will hold the value and type that implements it.</p>
<p>Another thing to notice is the output.</p>
<pre><code class="lang-go">ERROR:<span class="hljs-number">401</span>:GET:getUser
</code></pre>
<p>We are passing variable <code>err</code> of type <code>httpError struct</code> to the <code>fmt.Println</code> function, and it is printing nicely documented output, instead of messy struct variables.</p>
<p><strong><em>How?</em></strong></p>
<p>This is happening because we have defined the <code>Error</code> method that returns a custom error message string. So under the hood, the <code>fmt.Println</code> function is called the <code>Error</code> method and prints the returned string. So we never have to explicitly call the Error method to get a custom error message.</p>
<h2 id="heading-handling-errors-using-the-type-assertion">Handling errors using the type assertion</h2>
<p>In the above example, the variable <code>err</code> is of type interface. err variable will not have access to fields of httpError. But err is a variable of error interface and that interface is implemented by type httpError we can use type assertion to extract the underlying concrete value of the interface variable.</p>
<p>In the <strong><em>interfaces</em></strong> blog, we've seen how a type assertion is performed. By extracting this underlying value, we can gain more control over the error value, and we can decide how to return this information to the caller. Below is an illustrative example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> httpError <span class="hljs-keyword">struct</span> {
  code   <span class="hljs-keyword">int</span>
  method <span class="hljs-keyword">string</span>
  fn     <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(h *httpError)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
  <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"ERROR: %d:%s:%s\n"</span>, h.code, h.method, h.fn)
}

<span class="hljs-comment">//Mock function to demo some operation</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getUser</span><span class="hljs-params">(uid <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>{}, error)</span></span> {
  <span class="hljs-comment">// some business logic</span>
  authorized := <span class="hljs-literal">false</span>
  <span class="hljs-keyword">if</span> authorized {
  <span class="hljs-comment">//find user logic</span>
  <span class="hljs-keyword">return</span> <span class="hljs-string">"User found"</span>, <span class="hljs-literal">nil</span>
  }
  <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>, &amp;httpError{code: <span class="hljs-number">401</span>, method: <span class="hljs-string">"GET"</span>, fn: <span class="hljs-string">"getUser"</span>}
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  _, err := getUser(<span class="hljs-number">1</span>)
  <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">if</span> errVal, ok := err.(*httpError); ok {
      fmt.Printf(<span class="hljs-string">"Status Code: %d\n"</span>, errVal.code)
      fmt.Printf(<span class="hljs-string">"Method: %s\n"</span>, errVal.method)
      fmt.Printf(<span class="hljs-string">"function returned error: %s\n"</span>, errVal.fn)
    }
  }
}
</code></pre>
<pre><code class="lang-go">Status Code: <span class="hljs-number">401</span>
Method: GET
function returned error: getUser
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/cVIHQEKs1a5"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>This one is the same example as the previous one with a small tweak. Instead of printing the <code>err</code> variable, we are performing type assertion on it. Here <code>errVal, ok := err.(*httpError)</code> will return a pointer to the instance of the <code>httpError</code>. Now we can access the fields of the <code>httpError</code> struct using <code>errVal</code>.</p>
<p>In case the underlying error is not of type <code>*httpError</code>, then the <code>ok</code> the variable will be set to false returning control outside the if block.</p>
<h2 id="heading-handling-errors-using-type-switch">Handling errors using type switch</h2>
<p>Using a type switch we can check the type of error and handle it accordingly. Read more about type switch in the <strong><em>interfaces blog.</em></strong> Below is an illustrative example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> fooError <span class="hljs-keyword">struct</span> {
  msg <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(f *fooError)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
  <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Error: %s"</span>, f.msg)

}

<span class="hljs-keyword">type</span> barError <span class="hljs-keyword">struct</span> {
  msg <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(b *barError)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
  <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Error: %s"</span>, b.msg)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">doSomething</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> {
  <span class="hljs-keyword">return</span> &amp;fooError{<span class="hljs-string">"Something is wrong with foo!"</span>}
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  err := doSomething()

  <span class="hljs-keyword">switch</span> err.(<span class="hljs-keyword">type</span>) {
  <span class="hljs-keyword">case</span> <span class="hljs-literal">nil</span>:
    fmt.Println(<span class="hljs-string">"Everything is fine."</span>)
  <span class="hljs-keyword">case</span> *fooError:
    fmt.Println(<span class="hljs-string">"Foo: "</span>, err)
  <span class="hljs-keyword">case</span> *barError:
    fmt.Println(<span class="hljs-string">"Bar: "</span>, err)
  }
}
</code></pre>
<pre><code class="lang-go">Foo:  Error: Something is wrong with foo!
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/7tbNi8TmkBg"><strong><em>Run the code in Go Playground</em></strong></a></p>
<p>In the above example, <code>switch err.(type)</code> will discern the underlying type of the <code>err</code> variable and after comparing it with all the cases, the error will be handled by matched case.</p>
<p><strong><em>In this blog, we have seen:</em></strong></p>
<ul>
<li><p><em>What is an error in Golang?</em></p>
</li>
<li><p><em>How error is represented in Golang?</em></p>
</li>
<li><p><em>Implementing an error interface to create error</em></p>
</li>
<li><p><em>Using type assertion and type switch to extract more information about the error</em></p>
</li>
</ul>
<p><em>In the next blog, we'll see more about creating custom errors and handling them gracefully.</em></p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Interfaces in Go (Part-2)]]></title><description><![CDATA[Type assertion
Type assertion is used to get the underlying concrete value of the interface variable. i.(Type) this is the syntax of type assertion, where:
i -> interface variable
Type -> type that implements the interface
Let's see an example of typ...]]></description><link>https://pratikjagrut.space/interfaces-in-go-part-2</link><guid isPermaLink="true">https://pratikjagrut.space/interfaces-in-go-part-2</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Interfaces Go]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Fri, 21 Oct 2022 22:28:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/BgrRH1_ZI5Y/upload/3d2ec4853fcf7b5b4b59c1e04e76ead3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-type-assertion">Type assertion</h2>
<p>Type assertion is used to get the underlying concrete value of the interface variable. <code>i.(Type)</code> this is the syntax of type assertion, where:</p>
<p><code>i -&gt; interface variable</code></p>
<p><code>Type -&gt; type that implements the interface</code></p>
<p>Let's see an example of type assertion.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">interface</span> {
    info() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Student <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s Student)</span> <span class="hljs-title">info</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Student name is %s\n"</span>, s.name)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    s := Student{
        name: <span class="hljs-string">"Barry Allen"</span>,
    }
    <span class="hljs-keyword">var</span> p Person = s
    name := p.(Student)
    fmt.Println(name)
}
</code></pre>
<pre><code class="lang-go">{Barry Allen}
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/fzNWgZvcdVk"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, we create a Person interface which is then implicitly implemented by the Student struct by implementing the info method. <code>var p Person = s</code> this statement creates an interface variable <code>p</code> and assigns Student struct type variable <code>s</code> to it. <code>name := p.(Student)</code> this statement extracts the concrete value of the type <code>Student</code> and assign it to the <code>name</code> variable.</p>
<p>In the above program, type Student implements the Person interface and hence <code>p.(Student)</code> can hold the concrete value of type Student. But if <code>Type</code> from <code>i.(Type)</code> does not implement the interface then Go will throw a compilation error. Below is an illustrative example.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">interface</span> {
    info() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Student <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> p Person
    name := p.(Student)
    fmt.Println(name)
}
</code></pre>
<pre><code class="lang-go">./prog.<span class="hljs-keyword">go</span>:<span class="hljs-number">15</span>:<span class="hljs-number">11</span>: impossible <span class="hljs-keyword">type</span> assertion:
    Student does not implement Person (missing info method)
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/o7rOeX5EYKa"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>If the <code>Type</code> implements the interface but if the concrete value of that type is not available then Go will panic in runtime.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">interface</span> {
    info() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Student <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s Student)</span> <span class="hljs-title">info</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Student name is %s\n"</span>, s.name)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> p Person
    name := p.(Student)
    fmt.Println(name)
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-built_in">panic</span>: <span class="hljs-keyword">interface</span> conversion: main.Person is <span class="hljs-literal">nil</span>, not main.Student

goroutine <span class="hljs-number">1</span> [running]:
main.main()
    /tmp/sandbox657831697/prog.<span class="hljs-keyword">go</span>:<span class="hljs-number">19</span> +<span class="hljs-number">0x45</span>
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/yuLoDEbO3zr"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>Similarly, if the concrete type of interface variable does not match with <code>Type</code> of <code>i.(Type)</code> then the program will panic in runtime.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">interface</span> {
    info() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Student <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s Student)</span> <span class="hljs-title">info</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Student name is %s\n"</span>, s.name)
}

<span class="hljs-keyword">type</span> Teacher <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s Teacher)</span> <span class="hljs-title">info</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Teacher name is %s\n"</span>, s.name)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    t := Teacher{
        name: <span class="hljs-string">"Richard Feynman"</span>,
    }
    <span class="hljs-keyword">var</span> p Person = t
    name := p.(Student)
    fmt.Println(name)
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-built_in">panic</span>: <span class="hljs-keyword">interface</span> conversion: main.Person is main.Teacher, not main.Student

goroutine <span class="hljs-number">1</span> [running]:
main.main()
    /tmp/sandbox133075599/prog.<span class="hljs-keyword">go</span>:<span class="hljs-number">30</span> +<span class="hljs-number">0x45</span>
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/-6kfh5zgUXj"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>To avoid the above panic errors Go has another way for type assertion.</p>
<p><code>value, ok := i.(Type)</code></p>
<p>In the above syntax, <code>Ok</code> is a boolean variable. It will be false if <code>i.(Type)</code> has no concrete value and vice versa.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">interface</span> {
    info() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Student <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s Student)</span> <span class="hljs-title">info</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Student name is %s\n"</span>, s.name)
}

<span class="hljs-keyword">type</span> Teacher <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s Teacher)</span> <span class="hljs-title">info</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Teacher name is %s\n"</span>, s.name)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> p Person
    name, ok := p.(Student)
    fmt.Println(name, ok)

    t := Teacher{
        name: <span class="hljs-string">"Richard Feynman"</span>,
    }
    <span class="hljs-keyword">var</span> p1 Person = t
    name1, ok1 := p1.(Teacher)
    fmt.Println(name1, ok1)

    name2, ok2 := p1.(Student)
    fmt.Println(name2, ok2)
}
</code></pre>
<pre><code class="lang-go">{} <span class="hljs-literal">false</span>
{Richard Feynman} <span class="hljs-literal">true</span>
{} <span class="hljs-literal">false</span>
</code></pre>
<p><a target="_blank" href="https://go.dev/play/p/7_rvcrXwEA2"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h2 id="heading-type-switch">Type switch</h2>
<p>Type switch is similar to switch case statements where type switch compares the concrete type of an interface against types specified in cases. Below is the syntax of the type switch:</p>
<pre><code class="lang-go"><span class="hljs-keyword">switch</span> i.(<span class="hljs-keyword">type</span>) {
    <span class="hljs-keyword">case</span> <span class="hljs-keyword">float32</span>:
        <span class="hljs-comment">// Something to do</span>
    <span class="hljs-keyword">case</span> <span class="hljs-keyword">int</span>:
        <span class="hljs-comment">// Logic</span>
    <span class="hljs-keyword">default</span>:
        <span class="hljs-comment">// Default logic</span>
    }
</code></pre>
<p>Here <code>i.(type)</code> the syntax is fairly similar to type assertion syntax, where <code>i</code> is interface but instead of <code>value type</code> we use keyword <code>type</code>.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">guessType</span><span class="hljs-params">(i <span class="hljs-keyword">interface</span>{})</span></span> {
    <span class="hljs-keyword">switch</span> i.(<span class="hljs-keyword">type</span>) {
    <span class="hljs-keyword">case</span> <span class="hljs-keyword">string</span>:
        fmt.Println(<span class="hljs-string">"It is string"</span>)
    <span class="hljs-keyword">case</span> <span class="hljs-keyword">int</span>:
        fmt.Println(<span class="hljs-string">"It is Int"</span>)
    <span class="hljs-keyword">case</span> <span class="hljs-keyword">bool</span>:
        fmt.Println(<span class="hljs-string">"It is boolean"</span>)
    <span class="hljs-keyword">default</span>:
        fmt.Println(<span class="hljs-string">"IDK"</span>)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    guessType(<span class="hljs-number">10</span>)
    guessType(<span class="hljs-string">"Hello"</span>)
    guessType(<span class="hljs-literal">true</span>)
    guessType(<span class="hljs-number">10.11</span>)
}
</code></pre>
<pre><code class="lang-go">It is Int
It is <span class="hljs-keyword">string</span>
It is boolean
IDK
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/Z5RM_vGPSWF"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, we're passing an empty interface as an argument to function. The empty interface is implemented by all the types so we can pass any type of parameter while calling that function.</p>
<p><code>i.(type)</code> evaluates the concrete type of an interface and then a matching case is executed if none of the cases is matched then the default case is executed.</p>
<h2 id="heading-implementing-interfaces-using-pointer-receivers-vs-value-receivers">Implementing interfaces using pointer receivers vs value receivers</h2>
<p>In Golang methods can have both pointer or value as a receiver which restricts the accessibility of methods only to the type of its receiver. Methods from an interface can be pointers or values as a receiver in their implementation.</p>
<p><strong><em>Implementing interface with value receiver</em></strong></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> Car <span class="hljs-keyword">interface</span> {
    information()
}

<span class="hljs-keyword">type</span> Ferrari <span class="hljs-keyword">struct</span> {
    name   <span class="hljs-keyword">string</span>
    colour <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(f Ferrari)</span> <span class="hljs-title">information</span><span class="hljs-params">()</span></span> {
    fmt.Printf(<span class="hljs-string">"Name of the car: %s\n"</span>, f.name)
    fmt.Printf(<span class="hljs-string">"Colour of the car: %s\n"</span>, f.colour)
    fmt.Println()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> c1 Car

    f := Ferrari{
        name:   <span class="hljs-string">"SF90 STRADALE"</span>,
        colour: <span class="hljs-string">"ROSSO CORSA"</span>,
    }
    c1 = f
    c1.information()

}
</code></pre>
<pre><code class="lang-go">Name of the car: SF90 STRADALE
Colour of the car: ROSSO CORSA
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/D0hHbX-1g90"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above code, type <code>Ferrari</code> is implementing the method <code>information</code> from an interface <code>Car</code> with a value receiver and in the main function, we're assigning the variable <code>f</code> of struct <code>Ferrari</code> to variable <code>c1</code> of an interface <code>Car</code> and then calling <code>information</code> method using interface variables.</p>
<p><strong><em>Implementing interface with pointer receiver</em></strong></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> Car <span class="hljs-keyword">interface</span> {
    information()
}
<span class="hljs-keyword">type</span> Porsche <span class="hljs-keyword">struct</span> {
    name   <span class="hljs-keyword">string</span>
    colour <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p *Porsche)</span> <span class="hljs-title">information</span><span class="hljs-params">()</span></span> {
    fmt.Printf(<span class="hljs-string">"Name of the car: %s\n"</span>, p.name)
    fmt.Printf(<span class="hljs-string">"Colour of the car: %s\n"</span>, p.colour)
    fmt.Println()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {

    p := &amp;Porsche{
        name:   <span class="hljs-string">"718 SPYDER"</span>,
        colour: <span class="hljs-string">"BLACK"</span>,
    }
    <span class="hljs-keyword">var</span> c2 Car = p
    c2.information()
}
</code></pre>
<pre><code class="lang-go">Name of the car: <span class="hljs-number">718</span> SPYDER
Colour of the car: BLACK
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/fGVGiYL3qrJ"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above code, type <code>Porsche</code> is implementing the method <code>information</code> from an interface <code>Car</code> with a pointer receiver and in the main function we're assigning a variable pointer <code>p</code> of struct <code>Porsche</code> to variable <code>c2</code> of an interface <code>Car</code> and then calling <code>information</code> method using interface variables.</p>
<p>In Golang, a method with a value receiver or pointer receiver can be called on either value or pointer. It means if you're implementing a method with a value receiver then you can use a value or pointer of that type to call that method.</p>
<p><strong>But in the case of an interface does this phenomenon work?</strong></p>
<p><strong><em>Calling a method with value receiver on pointer type</em></strong></p>
<p>In the below code, we implement the method <code>information</code> with value receiver and call it on pointer type.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> Car <span class="hljs-keyword">interface</span> {
    information()
}

<span class="hljs-keyword">type</span> Ferrari <span class="hljs-keyword">struct</span> {
    name   <span class="hljs-keyword">string</span>
    colour <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(f Ferrari)</span> <span class="hljs-title">information</span><span class="hljs-params">()</span></span> {
    fmt.Printf(<span class="hljs-string">"Name of the car: %s\n"</span>, f.name)
    fmt.Printf(<span class="hljs-string">"Colour of the car: %s\n"</span>, f.colour)
    fmt.Println()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> c Car
    f1 := &amp;Ferrari{
        name:   <span class="hljs-string">"SF90 STRADALE"</span>,
        colour: <span class="hljs-string">"ROSSO CORSA"</span>,
    }
    c = f1
    c.information()
}
</code></pre>
<pre><code class="lang-go">Name of the car: SF90 STRADALE
Colour of the car: ROSSO CORSA
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/6OS8urGqkA5"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above code, the pointer to value conversion is done by Golang implicitly. It is valid to call a method with value type on any value or anything whose value can be dereferenced.</p>
<p><strong><em>Calling a method with a pointer receiver on the value type</em></strong></p>
<p>In the below code, we implement the method <code>information</code> with a pointer receiver and call it on the value type.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> Car <span class="hljs-keyword">interface</span> {
    information()
}

<span class="hljs-keyword">type</span> Porsche <span class="hljs-keyword">struct</span> {
    name   <span class="hljs-keyword">string</span>
    colour <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p *Porsche)</span> <span class="hljs-title">information</span><span class="hljs-params">()</span></span> {
    fmt.Printf(<span class="hljs-string">"Name of the car: %s\n"</span>, p.name)
    fmt.Printf(<span class="hljs-string">"Colour of the car: %s\n"</span>, p.colour)
    fmt.Println()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> c Car

    p := Porsche{
        name:   <span class="hljs-string">"718 SPYDER"</span>,
        colour: <span class="hljs-string">"BLACK"</span>,
    }
    c = p
    c.information()

}
</code></pre>
<pre><code class="lang-go">./prog.<span class="hljs-keyword">go</span>:<span class="hljs-number">29</span>:<span class="hljs-number">4</span>: cannot use p (<span class="hljs-keyword">type</span> Porsche) as <span class="hljs-keyword">type</span> Car in assignment:
    Porsche does not implement Car (information method has pointer receiver)
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/cP0WQqvbQbr"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above code, we're implementing the <code>information</code> method using a pointer receiver and then calling it on value type instead of a pointer, and we're getting a compilation error. <em>So what's happening?</em></p>
<p>If we look at the implementation of the <code>information</code> method it has a pointer receiver and we're calling it on <code>p</code> which is a value type and does not implement the <code>Car</code> interface. Hence we see the compilation error.</p>
<p>But in Golang, the method with value receiver or pointer receiver can be called on either value or pointer then why is this failing here?</p>
<p>This is because: it is completely valid to call the pointer receiver method using a pointer or using any value whose address can be obtained. In this case, the value type assigned to the interface variable is a concrete value of the interface whose address can not be obtained and hence we get that compilation error.</p>
<p><strong><em>Note: If we call a method directly with a struct variable then this issue will not occur.</em></strong></p>
<h2 id="heading-comparing-the-interfaces-variables">Comparing the interface's variables</h2>
<p>The two interface variables are comparable only if the <code>concrete value and concrete type</code> are comparable. Interface variables can be compared with <code>==</code> and <code>!=</code> operators.</p>
<p>If the concrete types or concrete values are not the same then the interface variables are not equal. If the concrete types or concrete values are the same then the interface variables are equal. Variables of an empty interface are always equal. <a target="_blank" href="https://Golang.org/ref/spec#Comparison_operators"><strong><em>Read more on Golang comparison operators.</em></strong></a></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Int <span class="hljs-keyword">int</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(i Int)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Value of Int is %d"</span>, i)
}

<span class="hljs-keyword">type</span> Float <span class="hljs-keyword">float32</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(f Float)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Value of Float is %f"</span>, f)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> i Int = <span class="hljs-number">10</span>
    <span class="hljs-keyword">var</span> f Float = <span class="hljs-number">5.5</span>

    <span class="hljs-keyword">var</span> v1 fmt.Stringer = i
    <span class="hljs-keyword">var</span> v2 fmt.Stringer = f

    fmt.Println(v1 == v2) <span class="hljs-comment">// false, because concrete types are not same</span>

    <span class="hljs-keyword">var</span> i1 Int = <span class="hljs-number">6</span>
    <span class="hljs-keyword">var</span> v3 fmt.Stringer = i1

    fmt.Println(v1 == v3) <span class="hljs-comment">// false, because concrete values are not same</span>

    <span class="hljs-keyword">var</span> f2 Float = <span class="hljs-number">5.5</span>
    <span class="hljs-keyword">var</span> v4 fmt.Stringer = f2

    fmt.Println(v2 == v4) <span class="hljs-comment">// true</span>

    <span class="hljs-keyword">var</span> m, n <span class="hljs-keyword">interface</span>{}
    fmt.Println(m == n) <span class="hljs-comment">// true</span>
}
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/crqoWj9PbmQ"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-some-good-resources-to-read">Some good resources to read</h3>
<p><a target="_blank" href="https://research.swtch.com/interfaces"><strong><em>Go Data Structures: Interfaces by Russ Cox</em></strong></a></p>
<p><a target="_blank" href="https://blog.golang.org/laws-of-reflection"><strong><em>The Laws of Reflection by Rob Pike</em></strong></a></p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Interfaces in Go (Part-1)]]></title><description><![CDATA[In Golang, an interface is a set of method signatures. When any type defines all the methods from an interface then that type implements the interface. So we can state that interface defines the behaviour of the object/type.
For example, an animal wa...]]></description><link>https://pratikjagrut.space/interfaces-in-go-part-1</link><guid isPermaLink="true">https://pratikjagrut.space/interfaces-in-go-part-1</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Interfaces Go]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Fri, 07 Oct 2022 22:23:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/BgrRH1_ZI5Y/upload/8cf47b730516cd951153f9f2df1badf3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Golang, an interface is a set of method signatures. When any type defines all the methods from an interface then that type implements the interface. So we can state that interface defines the behaviour of the object/type.</p>
<p>For example, an animal walks, eats and sleeps so we can have an interface <code>Animal</code> which declares the methods <code>walk, eat and sleep</code> and any animal e.g. <code>Tiger</code>, who walks, eats and sleeps so we say Tiger implements the animal interface.</p>
<p>Another example could be of shapes, any shape has an area and perimeter. So the <code>Shape</code> interface can declare <code>area</code> and <code>perimeter</code> methods and any shape such as a rectangle or triangle can implement a shape interface.</p>
<p>It is much similar to the OOP world's interface, where the interface specifies the methods and type decides how to implement them. In OOP programming we might have to use the <code>implement</code> keyword to explicitly implement the interface, but in Golang, if a type defines all the methods from an interface then it <code>implicitly implements</code> interface.</p>
<h2 id="heading-declaring-and-implementing-interface">Declaring and Implementing Interface</h2>
<p>To declare an interface in Golang we use the <code>type</code> and <code>interface</code> keyword. Below is a syntax:</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> InterfaceName <span class="hljs-keyword">interface</span> {
  <span class="hljs-comment">// Method declaration</span>
}
</code></pre>
<p><code>Stringer</code> the interface is declared in the <code>fmt</code> package, which has a signature of the only one method <code>String</code>.</p>
<p><a target="_blank" href="https://Golang.org/pkg/fmt/#Stringer"><strong><em>fmt.Stringer doc</em></strong></a></p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Stringer <span class="hljs-keyword">interface</span> {
    String() <span class="hljs-keyword">string</span>
}
</code></pre>
<p>To implement a particular interface a type needs to implement all the methods with the exact names and signatures defined in that interface. <code>Interfaces in Go are implicitly implemented.</code></p>
<p>Below is an implementation of the <code>fmt.Stringer</code> interface from the standard library.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name    <span class="hljs-keyword">string</span>
    age     <span class="hljs-keyword">int</span>
    address Address
}

<span class="hljs-keyword">type</span> Address <span class="hljs-keyword">struct</span> {
    city, country <span class="hljs-keyword">string</span>
    pincode       <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p Person)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"My name is '%s', I'm '%d' years old, I love in '%s', '%s'"</span>, p.name, p.age, p.address.city, p.address.country)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    person := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        address: Address{
            city:    <span class="hljs-string">"London"</span>,
            pincode: <span class="hljs-number">123456</span>,
            country: <span class="hljs-string">"UK"</span>,
        },
    }

    address := Address{
        city:    <span class="hljs-string">"London"</span>,
        country: <span class="hljs-string">"UK"</span>,
        pincode: <span class="hljs-number">123456</span>,
    }

    fmt.Println(person)
    fmt.Println(address)
}
</code></pre>
<pre><code class="lang-go">My name is <span class="hljs-string">'James Bond'</span>, I<span class="hljs-string">'m '</span><span class="hljs-number">34</span><span class="hljs-string">' years old, I love in '</span>London<span class="hljs-string">', '</span>UK<span class="hljs-string">'
{London UK 123456}</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/0C_8uGzb04A"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, we've two structs one is <code>Person</code> and the other one is <code>Address</code> and only the <code>Person</code> struct implements the <code>Stringer</code> interface by implementing the <code>String()</code> method because of which we could print the custom string format output.</p>
<p>Notice the output, the <code>person</code> variable has its custom string and the <code>address</code> variable prints output in curly braces.</p>
<p>Once a type implements an interface then the method implemented by that type can also be called using an interface variable.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> Shape <span class="hljs-keyword">interface</span> {
    Area()
}

<span class="hljs-keyword">type</span> Square <span class="hljs-keyword">struct</span> {
    side <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s Square)</span> <span class="hljs-title">Area</span><span class="hljs-params">()</span></span> {
    fmt.Printf(<span class="hljs-string">"Area of the square is %d\n"</span>, s.side*s.side)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    sq := Square{
        side: <span class="hljs-number">10</span>,
    }
    <span class="hljs-keyword">var</span> sh Shape = sq
    sq.Area()
    sh.Area()
}
</code></pre>
<pre><code class="lang-go">Area of the square is <span class="hljs-number">100</span>
Area of the square is <span class="hljs-number">100</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/cQmfCtE3GMC"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above program, type <code>Square</code> is implementing the <code>Shape</code> interface. In the main function, we call the implemented method <code>Area</code> on variable <code>sq</code> of type <code>Square</code> and on variable <code>sh</code> of type <code>Shape</code> interface and the program still work fine.</p>
<h2 id="heading-interfaces-types-and-values">Interface's types and values</h2>
<p>The variable of an interface stores, a concrete value and the type of that concrete value is called concrete type. This representation can be envisaged as a tuple <code>(type, value)</code>. An interface variable can store any concrete type and value as long as that type and value implement the interface's method. The below program illustrates the type and value of the interface.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Int <span class="hljs-keyword">int</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(i Int)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Value of Int is %d"</span>, i)
}

<span class="hljs-keyword">type</span> Float <span class="hljs-keyword">float32</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(f Float)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Value of Float is %f"</span>, f)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">describe</span><span class="hljs-params">(s fmt.Stringer)</span></span> {
    fmt.Printf(<span class="hljs-string">"Concrete type of an interface is %T\n"</span>, s)
    fmt.Printf(<span class="hljs-string">"%v\n"</span>, s)
    fmt.Println()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> s fmt.Stringer
    describe(s)

    <span class="hljs-keyword">var</span> i Int = <span class="hljs-number">10</span>
    s = i
    describe(s)

    <span class="hljs-keyword">var</span> f Float = <span class="hljs-number">15.0005</span>
    s = f
    describe(f)
}
</code></pre>
<pre><code class="lang-go">Concrete <span class="hljs-keyword">type</span> of an <span class="hljs-keyword">interface</span> is &lt;<span class="hljs-literal">nil</span>&gt;
&lt;<span class="hljs-literal">nil</span>&gt;

Concrete <span class="hljs-keyword">type</span> of an <span class="hljs-keyword">interface</span> is main.Int
Value of Int is <span class="hljs-number">10</span>

Concrete <span class="hljs-keyword">type</span> of an <span class="hljs-keyword">interface</span> is main.Float
Value of Float is <span class="hljs-number">15.000500</span>
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/9_yZVvc3gsa"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above program:</p>
<p>We create two customs types Int and Float whose underlying types are int and float32 respectively. Both types implement <code>fmt.Stringer</code> interface by implementing <code>String() string</code> the function.</p>
<p>The statement <code>var s fmt.Stringer</code> creates a variable of an interface fmt.Stringer with zero value <code>&lt;nil&gt;</code>.</p>
<p>In the main function, we assign variables of type Int and Float to the interface variable s. This means when a particular type implements an interface then the variable of that type can also be represented as the type of an interface.</p>
<p>The type and value of the interface depend on the type and which implements that interface. Sometimes the concrete type and value of an interface are also called dynamic type and value. We call it dynamic because we can assign any type to the interface as long as that type implements the interface.</p>
<h3 id="heading-zero-value-of-an-interface">Zero Value of an interface</h3>
<p>The zero value of an interface is <code>&lt;nil&gt;</code>. A nil interface has its concrete value and concrete type nil.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> s fmt.Stringer
    fmt.Printf(<span class="hljs-string">"The concrete type of a nil interface is %T\n"</span>, s)
    fmt.Printf(<span class="hljs-string">"The concrete value of a nil interface is %v"</span>, s)
}
</code></pre>
<pre><code class="lang-go">The concrete <span class="hljs-keyword">type</span> of a <span class="hljs-literal">nil</span> <span class="hljs-keyword">interface</span> is &lt;<span class="hljs-literal">nil</span>&gt;
The concrete value of a <span class="hljs-literal">nil</span> <span class="hljs-keyword">interface</span> is &lt;<span class="hljs-literal">nil</span>&gt;
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/8GKGXSwOEOw"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>If we try to call a method on a nil interface, the program will panic.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Day <span class="hljs-keyword">string</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(day Day)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">string</span>(day)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> s fmt.Stringer
    fmt.Println(<span class="hljs-string">"The day is "</span>, s.String())
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-built_in">panic</span>: runtime error: invalid memory address or <span class="hljs-literal">nil</span> pointer dereference
[signal SIGSEGV: segmentation violation code=<span class="hljs-number">0x1</span> addr=<span class="hljs-number">0x0</span> pc=<span class="hljs-number">0x497683</span>]

goroutine <span class="hljs-number">1</span> [running]:
main.main()
    /tmp/sandbox117008893/prog.<span class="hljs-keyword">go</span>:<span class="hljs-number">13</span> +<span class="hljs-number">0x23</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/9KwItPMGxWD"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>The error pretty much is self-explanatory. The underlying concrete value and type are nil so the method can not be called on that object.</p>
<h2 id="heading-empty-interface">Empty Interface</h2>
<p>An interface with zero methods is called an empty interface. The empty interface is represented by <code>interface{}</code>.</p>
<p>Since an empty interface has no methods it is implemented by all the types. Let's dive into an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getType</span><span class="hljs-params">(s <span class="hljs-keyword">interface</span>{})</span></span> {
    fmt.Printf(<span class="hljs-string">"%T\n"</span>, s)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    i := <span class="hljs-number">10</span>
    getType(i)

    s := <span class="hljs-string">"Hola"</span>
    getType(s)

    f := <span class="hljs-number">12.24</span>
    getType(f)

    b := <span class="hljs-literal">true</span>
    getType(b)
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-keyword">int</span>
<span class="hljs-keyword">string</span>
<span class="hljs-keyword">float64</span>
<span class="hljs-keyword">bool</span>
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/m6GMNMIBAUo"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>The function <code>getType(s interface{})</code> accepts an empty interface as an argument hence we were able to pass any type of variable to the function.</p>
<p>Have you ever wondered how the <code>Println</code> function can accept any number of values of different different types and print it? The answer is <code>interface{}</code>.</p>
<p>This is the signature of the <code>Println</code> function <code>func Println(a ...interface{}) (n int, err error)</code>. The Println function is a <code>variadic function</code> which can take arguments of the type <code>interface{}</code>.</p>
<h2 id="heading-implementing-multiple-interfaces">Implementing multiple interfaces</h2>
<p>A type can implement more than one interface. Let's see how it is done.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
   <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> Shape <span class="hljs-keyword">interface</span> {
   Area()
}

<span class="hljs-keyword">type</span> Quadrilateral <span class="hljs-keyword">interface</span> {
   isQuadrilateral() <span class="hljs-keyword">bool</span>
}

<span class="hljs-keyword">type</span> square <span class="hljs-keyword">struct</span> {
   noOfSides <span class="hljs-keyword">int</span>
   side      <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s square)</span> <span class="hljs-title">Area</span><span class="hljs-params">()</span></span> {
   fmt.Printf(<span class="hljs-string">"Area of the square is %d\n"</span>, s.side*s.side)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s square)</span> <span class="hljs-title">isQuadrilateral</span><span class="hljs-params">()</span> <span class="hljs-title">bool</span></span> {
   <span class="hljs-keyword">if</span> s.noOfSides == <span class="hljs-number">4</span> {
       <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
   }
   <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
   s := square{
       noOfSides: <span class="hljs-number">4</span>,
       side:      <span class="hljs-number">10</span>,
   }

   <span class="hljs-keyword">var</span> sh Shape = s
   sh.Area()

   <span class="hljs-keyword">var</span> q Quadrilateral = s
   fmt.Println(q.isQuadrilateral())
}
</code></pre>
<pre><code class="lang-go">Area of the square is <span class="hljs-number">100</span>
<span class="hljs-literal">true</span>
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/1alfdI_h-DW"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, we've two interfaces <code>Shape</code> and <code>Quadrilateral</code>. Type <code>square</code> implements both interfaces. The program is easy and self-explanatory.</p>
<h2 id="heading-embedding-interfaces">Embedding interfaces</h2>
<p>In Golang, one interface can embed any other interface. Golang does not support inheritance but this embedding of interfaces can give a sense of inheritance. Below is an illustrative example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> Shape <span class="hljs-keyword">interface</span> {
    Area()
}

<span class="hljs-keyword">type</span> Quadrilateral <span class="hljs-keyword">interface</span> {
    Shape
    fmt.Stringer
    isQuadrilateral() <span class="hljs-keyword">bool</span>
}

<span class="hljs-keyword">type</span> square <span class="hljs-keyword">struct</span> {
    noOfSides <span class="hljs-keyword">int</span>
    side      <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s square)</span> <span class="hljs-title">Area</span><span class="hljs-params">()</span></span> {
    fmt.Printf(<span class="hljs-string">"Area of the square is %d\n"</span>, s.side*s.side)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s square)</span> <span class="hljs-title">isQuadrilateral</span><span class="hljs-params">()</span> <span class="hljs-title">bool</span></span> {
    <span class="hljs-keyword">if</span> s.noOfSides == <span class="hljs-number">4</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s square)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"Number of sides are %d and dimension of side is %d"</span>, s.noOfSides, s.side)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    s := square{
        noOfSides: <span class="hljs-number">4</span>,
        side:      <span class="hljs-number">10</span>,
    }
    <span class="hljs-keyword">var</span> q Quadrilateral = s
    fmt.Println(s.String())
    s.Area()
    fmt.Println(q.isQuadrilateral())
}
</code></pre>
<pre><code class="lang-go">Number of sides are <span class="hljs-number">4</span> and dimension of side is <span class="hljs-number">10</span>
Area of the square is <span class="hljs-number">100</span>
<span class="hljs-literal">true</span>
</code></pre>
<p><a target="_blank" href="https://play.Golang.org/p/UOQv16mFLn7"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, we have <code>Shape</code> and <code>fmt.Stringer</code> interfaces which are embedded in the <code>Quadrilateral</code> interface. The type <code>square</code> implements method from <code>Shape</code>, <code>fmt.Stringer</code> and <code>Quadrilateral</code> interfaces. In the main function, we're creating a variable of type <code>square</code> and assigning it to the variable of the <code>Quadrilateral</code> interface. After that, we're calling all the methods implemented by type <code>square</code> using only the variable of the <code>Quadrilateral</code> interface.</p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Structs in Go (Part-2)]]></title><description><![CDATA[Nested Structs
Go allows us to use a struct as a field of another struct, this pattern is called nesting. A nested struct can be defined using the following syntax.
type struct1 struct{
    // fields
}

type struct2 struct{
    // fields
    s struct...]]></description><link>https://pratikjagrut.space/structs-in-go-part-2</link><guid isPermaLink="true">https://pratikjagrut.space/structs-in-go-part-2</guid><category><![CDATA[struct]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[tutorials]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Fri, 23 Sep 2022 22:16:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/26MJGnCM0Wc/upload/02071456d6c15892a43837edcde6cdc9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-nested-structs">Nested Structs</h2>
<p>Go allows us to use a struct as a field of another struct, this pattern is called nesting. A nested struct can be defined using the following syntax.</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> struct1 <span class="hljs-keyword">struct</span>{
    <span class="hljs-comment">// fields</span>
}

<span class="hljs-keyword">type</span> struct2 <span class="hljs-keyword">struct</span>{
    <span class="hljs-comment">// fields</span>
    s struct1
}
</code></pre>
<p>Suppose we need to collect the data of a person, the person's name, age and address. In the address, we need to collect the city and country of that person. So we can do this using nested structs as shown below:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name    <span class="hljs-keyword">string</span>
    age     <span class="hljs-keyword">int</span>
    address Address
}

<span class="hljs-keyword">type</span> Address <span class="hljs-keyword">struct</span> {
    city, country <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    person := &amp;Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        address: Address{
            city:    <span class="hljs-string">"London"</span>,
            country: <span class="hljs-string">"UK"</span>,
        },
    }

    fmt.Printf(<span class="hljs-string">"%#v"</span>, person)
}
</code></pre>
<pre><code class="lang-go">&amp;main.Person{name:<span class="hljs-string">"James Bond"</span>, age:<span class="hljs-number">34</span>, address:main.Address{city:<span class="hljs-string">"London"</span>, country:<span class="hljs-string">"UK"</span>}}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/e4A9YhIirqW"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-accessing-fields-of-nested-struct">Accessing fields of nested struct</h3>
<p>To access the fields of nested structs we can do <code>structObj1.structObj2.structObj3........fieldName</code>.</p>
<p>Below is an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name    <span class="hljs-keyword">string</span>
    age     <span class="hljs-keyword">int</span>
    address Address
}

<span class="hljs-keyword">type</span> Address <span class="hljs-keyword">struct</span> {
    city, country <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    person := &amp;Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        address: Address{
            city:    <span class="hljs-string">"London"</span>,
            country: <span class="hljs-string">"UK"</span>,
        },
    }

    fmt.Printf(<span class="hljs-string">"Name: %v\n"</span>, person.name)
    fmt.Printf(<span class="hljs-string">"Age: %v\n"</span>, person.age)
    fmt.Printf(<span class="hljs-string">"City: %v\n"</span>, person.address.city)
    fmt.Printf(<span class="hljs-string">"Country: %v\n"</span>, person.address.country)
}
</code></pre>
<pre><code class="lang-go">Name: James Bond
Age: <span class="hljs-number">34</span>
City: London
Country: UK
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/OTkVLWQRf3Q"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-promoted-fields">Promoted fields</h3>
<p>When the struct has another struct as an anonymous field then fields of anonymous structs are called promoted fields. This means we can access the fields of the nested struct without using the object of the nested struct, we can access them just by using the parent struct.</p>
<p>For example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
    Address
}

<span class="hljs-keyword">type</span> Address <span class="hljs-keyword">struct</span> {
    city, country <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    person := &amp;Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        Address: Address{
            city:    <span class="hljs-string">"London"</span>,
            country: <span class="hljs-string">"UK"</span>,
        },
    }

    fmt.Printf(<span class="hljs-string">"Name: %v\n"</span>, person.name)
    fmt.Printf(<span class="hljs-string">"Age: %v\n"</span>, person.age)
    fmt.Printf(<span class="hljs-string">"City: %v\n"</span>, person.city) <span class="hljs-comment">// Instead of person.address.city we used person.city</span>
    fmt.Printf(<span class="hljs-string">"Country: %v\n"</span>, person.country) <span class="hljs-comment">// Instead of person.address.country we used person.country</span>
}
</code></pre>
<pre><code class="lang-go">Name: James Bond
Age: <span class="hljs-number">34</span>
City: London
Country: UK
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/wkxWR0u6zoT"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong><em>Only unique fields of nested anonymous struct gets promoted.</em></strong></p>
<p>If the parent struct and nested anonymous struct have the same name field then that field will not be promoted.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
    City
}

<span class="hljs-keyword">type</span> City <span class="hljs-keyword">struct</span> {
    name, country <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    person := &amp;Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        City: City{
            name:    <span class="hljs-string">"London"</span>,
            country: <span class="hljs-string">"UK"</span>,
        },
    }

    fmt.Printf(<span class="hljs-string">"Name: %v\n"</span>, person.name)
    fmt.Printf(<span class="hljs-string">"Age: %v\n"</span>, person.age)
    fmt.Printf(<span class="hljs-string">"City: %v\n"</span>, person.City.name)
    fmt.Printf(<span class="hljs-string">"Country: %v\n"</span>, person.country)
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/gklcUfcRJV9"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In this example, we have <code>City</code> a nested anonymous struct, whose fields are <code>name</code> and <code>country</code>. The <code>name</code> the field is also available in the <code>Person</code> struct. So when we try <code>person.name</code> then the compiler will give us access to the Person's name field by default hence to access the name field from the City struct we've to do <code>person.City.name</code>. The country field from City struct is unique here so we can just access it by using <code>person.country</code>.</p>
<h2 id="heading-comparing-struct">Comparing struct</h2>
<p>Structs in Go are value type and so they can be compared.</p>
<p>Two struct values may be equal if:</p>
<ul>
<li><p>They're of the same type.</p>
</li>
<li><p>Their corresponding fields are equal.</p>
</li>
<li><p>Their corresponding fields should be comparable.</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p1 := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
    }

    p2 := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
    }

    fmt.Println(p1 == p2) <span class="hljs-comment">// true</span>
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/KZrnjv-8qC1"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong><em>Comparing pointers to the struct will always be false, we need to compare dereferenced pointer values.</em></strong></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p1 := &amp;Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
    }

    p2 := &amp;Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
    }
    fmt.Println(p1 == p2) <span class="hljs-comment">// false</span>
    fmt.Println(*p1 == *p2) <span class="hljs-comment">// true</span>
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/qcQYTF_BUcP"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>If structs contain incomparable values then struct values can not be compared using <code>==</code> operator, it will throw an error.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name     <span class="hljs-keyword">string</span>
    age      <span class="hljs-keyword">int</span>
    measures <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">float32</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p1 := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        measures: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">float32</span>{
            <span class="hljs-string">"Height"</span>: <span class="hljs-number">183</span>,
            <span class="hljs-string">"Weight"</span>: <span class="hljs-number">76</span>,
        },
    }

    p2 := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        measures: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">float32</span>{
            <span class="hljs-string">"Height"</span>: <span class="hljs-number">183</span>,
            <span class="hljs-string">"Weight"</span>: <span class="hljs-number">76</span>,
        },
    }
    fmt.Println(p1 == p2)
}
</code></pre>
<pre><code class="lang-go">./prog.<span class="hljs-keyword">go</span>:<span class="hljs-number">30</span>:<span class="hljs-number">18</span>: invalid operation: p1 == p2 (<span class="hljs-keyword">struct</span> containing <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">float32</span> cannot be compared)
</code></pre>
<p>In the above code, a map is used as a field in a struct and a map is an incomparable type. To compare such structs we can use <code>reflect.DeepEqual()</code> function.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"reflect"</span>
)

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name     <span class="hljs-keyword">string</span>
    age      <span class="hljs-keyword">int</span>
    measures <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">float32</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p1 := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        measures: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">float32</span>{
            <span class="hljs-string">"Height"</span>: <span class="hljs-number">183</span>,
            <span class="hljs-string">"Weight"</span>: <span class="hljs-number">76</span>,
        },
    }

    p2 := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
        measures: <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">float32</span>{
            <span class="hljs-string">"Height"</span>: <span class="hljs-number">183</span>,
            <span class="hljs-string">"Weight"</span>: <span class="hljs-number">76</span>,
        },
    }
    fmt.Println(reflect.DeepEqual(p1, p2)) <span class="hljs-comment">// true</span>
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/R1nK7gPUcrt"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h2 id="heading-structs-and-methodsreceiver-function">Structs and methods/receiver function</h2>
<p>Golang supports both function and method. A method is a function that is defined for a particular type or with a receiver. A method in Golang is also called a receiver function. Following is the example.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p Person)</span> <span class="hljs-title">GetInfo</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"\"%v\" is \"%v\" years old."</span>, p.name, p.age)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
    }

    fmt.Println(p.GetInfo())
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-string">"James Bond"</span> is <span class="hljs-string">"34"</span> years old.
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/NnCg1hi-t2d"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>We can also use a pointer as the receiver of the method. The difference between value as receiver and pointer as a receiver is, golang passes everything as value and hence in value receiver the function will get a copy of the struct and function will not touch the original struct whereas in pointer as a receiver function will get a copy of a pointer which will be pointing to an original struct.</p>
<p>The below examples illustrate the difference between a pointer and a value as a receiver.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-comment">// Value as receiver</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p Person)</span> <span class="hljs-title">UpdateAge</span><span class="hljs-params">(age <span class="hljs-keyword">int</span>)</span></span> {
    p.age = age
}

<span class="hljs-comment">// Pointer as receiver</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p *Person)</span> <span class="hljs-title">UpdateName</span><span class="hljs-params">(name <span class="hljs-keyword">string</span>)</span></span> {
    p.name = name
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p := Person{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">34</span>,
    }

    <span class="hljs-comment">// Value as receiver example</span>
    fmt.Println(<span class="hljs-string">"Age before update: "</span>, p.age)
    p.UpdateAge(<span class="hljs-number">24</span>)
    fmt.Println(<span class="hljs-string">"Age after update: "</span>, p.age)

    fmt.Println()

    <span class="hljs-comment">// Pointer as receiver</span>
    fmt.Println(<span class="hljs-string">"Name before update: "</span>, p.name)
    p.UpdateName(<span class="hljs-string">"Jon Snow"</span>)
    fmt.Println(<span class="hljs-string">"Name after update: "</span>, p.name)
}
</code></pre>
<p>In above example <code>UpdateAge()</code> is using value as the receiver and <code>UpdateName()</code> is using pointer as a receiver.</p>
<pre><code class="lang-go">Age before update:  <span class="hljs-number">34</span>
Age after update:  <span class="hljs-number">34</span>

Name before update:  James Bond
Name after update:  Jon Snow
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/gvDMobx70PK"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h2 id="heading-empty-struct">Empty Struct</h2>
<p>In Golang, we can have an empty struct. A struct without any field is called an empty struct. Below is the signature of an empty struct.</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> T <span class="hljs-keyword">struct</span>{}
<span class="hljs-keyword">var</span> s <span class="hljs-keyword">struct</span>{}
</code></pre>
<p>Empty struct does not have any field so it does not occupy any memory i.e it occupies <code>zero bytes</code> of storage.</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> s <span class="hljs-keyword">struct</span>{}
fmt.Println(unsafe.Sizeof(s)) <span class="hljs-comment">// prints 0</span>
</code></pre>
<p>We can create an array of the empty struct and still it occupies zero bytes.</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> arr [<span class="hljs-number">100000</span>]<span class="hljs-keyword">struct</span>{}
fmt.Println(unsafe.Sizeof(arr)) <span class="hljs-comment">// prints 0</span>
</code></pre>
<p>The slice of structs will consume some bytes just to store the pointer, length and capacity of an underlying array but structs still will be of zero bytes.</p>
<pre><code class="lang-go">sls := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">struct</span>{}, <span class="hljs-number">100000</span>)
fmt.Println(unsafe.Sizeof(sls)) <span class="hljs-comment">// prints 24</span>
</code></pre>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"unsafe"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> s <span class="hljs-keyword">struct</span>{}
    fmt.Println(<span class="hljs-string">"Size of an empty struct: "</span>, unsafe.Sizeof(s)) <span class="hljs-comment">// prints 0</span>

    <span class="hljs-keyword">var</span> arr [<span class="hljs-number">100000</span>]<span class="hljs-keyword">struct</span>{}
    fmt.Println(<span class="hljs-string">"Size of an array of an empty struct: "</span>, unsafe.Sizeof(arr)) <span class="hljs-comment">// prints 0</span>

    sls := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">struct</span>{}, <span class="hljs-number">100000</span>)
    fmt.Println(<span class="hljs-string">"Size of a slice of an empty struct: "</span>, unsafe.Sizeof(sls)) <span class="hljs-comment">// prints 24</span>
}
</code></pre>
<pre><code class="lang-go">Size of an empty <span class="hljs-keyword">struct</span>:  <span class="hljs-number">0</span>
Size of an array of an empty <span class="hljs-keyword">struct</span>:  <span class="hljs-number">0</span>
Size of a slice of an empty <span class="hljs-keyword">struct</span>:  <span class="hljs-number">24</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/SB9x1tSICW1"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>Read more about the empty struct and its use cases at <a target="_blank" href="https://dave.cheney.net/2014/03/25/the-empty-struct"><strong><em>Dave Cheney's blog.</em></strong></a></p>
<h2 id="heading-arrayslice-of-structs">Array/Slice of structs</h2>
<p>The <strong><em>Array/Slice</em></strong> is a collection of the same type of element in a contiguous memory location. We can create an array/slice of structs.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">newPerson</span><span class="hljs-params">(name <span class="hljs-keyword">string</span>, age <span class="hljs-keyword">int</span>)</span> *<span class="hljs-title">Person</span></span> {
    <span class="hljs-keyword">return</span> &amp;Person{
        name: name,
        age:  age,
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    people := <span class="hljs-built_in">make</span>([]*Person, <span class="hljs-number">0</span>) <span class="hljs-comment">// slice of a struct Person with initial length 0</span>

    people = <span class="hljs-built_in">append</span>(people, newPerson(<span class="hljs-string">"James Bond"</span>, <span class="hljs-number">34</span>))
    people = <span class="hljs-built_in">append</span>(people, newPerson(<span class="hljs-string">"Jon Snow"</span>, <span class="hljs-number">24</span>))
    people = <span class="hljs-built_in">append</span>(people, newPerson(<span class="hljs-string">"Joey Tribbiani"</span>, <span class="hljs-number">32</span>))

    <span class="hljs-keyword">for</span> _, person := <span class="hljs-keyword">range</span> people {
        fmt.Println(person)
    }

    fmt.Println(<span class="hljs-string">"Name of friends character: "</span>, people[<span class="hljs-number">2</span>].name)
}
</code></pre>
<pre><code class="lang-go">&amp;{James Bond <span class="hljs-number">34</span>}
&amp;{Jon Snow <span class="hljs-number">24</span>}
&amp;{Joey Tribbiani <span class="hljs-number">32</span>}
Name of friends character:  Joey Tribbiani
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/g9-754U92un"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Structs in Go (Part-1)]]></title><description><![CDATA[What is Struct?
A struct is a sequence of named elements, called fields, each of which has a name and a type. Field names may be specified explicitly (IdentifierList) or implicitly (EmbeddedField). Within a struct, non-blank field names must be uniqu...]]></description><link>https://pratikjagrut.space/structs-in-go-part-1</link><guid isPermaLink="true">https://pratikjagrut.space/structs-in-go-part-1</guid><category><![CDATA[Go Language]]></category><category><![CDATA[struct]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Sat, 17 Sep 2022 22:10:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/26MJGnCM0Wc/upload/02071456d6c15892a43837edcde6cdc9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-struct">What is Struct?</h2>
<p>A struct is a sequence of named elements, called fields, each of which has a name and a type. Field names may be specified explicitly (IdentifierList) or implicitly (EmbeddedField). Within a struct, non-blank field names must be unique. <a target="_blank" href="https://golang.org/ref/spec#Struct_types"><strong><em>From golang docs.</em></strong></a></p>
<p>In simple words, a struct is a user-defined type that allows the collection of different types of elements. These elements are called fields. Structs can be used to keep certain data together. A struct is a very popular and widely used user-defined type in golang.</p>
<h2 id="heading-struct-declaration-and-initialization">Struct Declaration and Initialization</h2>
<p>A struct is defined using keywords <code>type</code> and <code>struct</code>. The type keyword is used to define user-defined data types and the struct keyword specifies that it's a struct.</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name    <span class="hljs-keyword">string</span>
    age     <span class="hljs-keyword">int</span>
}
</code></pre>
<p>To use the struct we create a struct object.</p>
<p><code>var p Person</code> or shorthand <code>p := Person{}</code> will create an object of struct Person and will initialize its field with the zero-value of their type.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name    <span class="hljs-keyword">string</span>
    age     <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> p Person
    fmt.Printf(<span class="hljs-string">"%#v"</span>, p)

    p1 := Person{}
    fmt.Printf(<span class="hljs-string">"%#v\n"</span>, p1)
}
</code></pre>
<pre><code class="lang-go">main.Person{name:<span class="hljs-string">""</span>, age:<span class="hljs-number">0</span>}
main.Person{name:<span class="hljs-string">""</span>, age:<span class="hljs-number">0</span>}
</code></pre>
<p><code>%#v</code> a Go-syntax representation of the value.</p>
<p><a target="_blank" href="https://play.golang.org/p/APy03otXxrI"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong><em>Struct literals</em></strong></p>
<p>Creating a struct object with specifying field names</p>
<pre><code class="lang-go">p := Person{name: <span class="hljs-string">"Jon Snow"</span>, age: <span class="hljs-number">24</span>}
p1 := Person{
    name: <span class="hljs-string">"Jon Snow"</span>,
    age:  <span class="hljs-number">24</span>,
}
</code></pre>
<p>The order of the field does not matter when specifying field names</p>
<pre><code class="lang-go">p := Person{age: <span class="hljs-number">24</span>, name: <span class="hljs-string">"Jon Snow"</span>}
</code></pre>
<p>Creating a struct object without specifying field names</p>
<pre><code class="lang-go">p := Person{<span class="hljs-string">"Jon Snow"</span>, <span class="hljs-number">24</span>}
p1 := Person{
  <span class="hljs-string">"Jon Snow"</span>,
  <span class="hljs-number">24</span>,
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p := Person{name: <span class="hljs-string">"Jon Snow"</span>, age: <span class="hljs-number">24</span>}
    fmt.Printf(<span class="hljs-string">"%#v\n"</span>, p)

    p1 := Person{<span class="hljs-string">"Jon Snow"</span>, <span class="hljs-number">24</span>}
    fmt.Printf(<span class="hljs-string">"%#v\n"</span>, p1)

    p2 := Person{
        name: <span class="hljs-string">"Jon Snow"</span>,
        age:  <span class="hljs-number">24</span>,
    }
    fmt.Printf(<span class="hljs-string">"%#v\n"</span>, p2)

    p3 := Person{
        <span class="hljs-string">"Jon Snow"</span>,
        <span class="hljs-number">24</span>,
    }
    fmt.Printf(<span class="hljs-string">"%#v\n"</span>, p3)
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/Ec0BcnT7dwg"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h2 id="heading-accessing-struct-fields">Accessing struct fields</h2>
<p>To access individual fields of the struct, <code>.</code> (dot) operator is used. e.g.<code>struct.fieldname</code>.</p>
<p>To use the value present in a struct field.</p>
<pre><code class="lang-go">value := <span class="hljs-keyword">struct</span>.fieldname
</code></pre>
<p>To assign a new value to the struct field</p>
<pre><code class="lang-go"><span class="hljs-keyword">struct</span>.fieldname = value
</code></pre>
<p>The below example demonstrates how to access the struct fields.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p := Person{name: <span class="hljs-string">"Jon Snow"</span>, age: <span class="hljs-number">24</span>}
    fmt.Printf(<span class="hljs-string">"Name of the person: %v\n"</span>, p.name)
    fmt.Printf(<span class="hljs-string">"Age of the person: %v\n"</span>, p.age)

    p.age = <span class="hljs-number">30</span>
    fmt.Printf(<span class="hljs-string">"Updated age of the person: %v\n"</span>, p.age)
}
</code></pre>
<pre><code class="lang-go">Name of the person: Jon Snow
Age of the person: <span class="hljs-number">24</span>
Age of the person: <span class="hljs-number">30</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/jL6nC8aoHZs"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h2 id="heading-pointer-to-the-struct">Pointer to the struct</h2>
<p><a target="_blank" href="/blog/golang/series/pointers">Pointers</a> are special variable that stores the address of another variable. We can store the address of a struct object in a pointer by passing the memory address using <code>&amp;</code> operator.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// First way of creating pointer to struct</span>
    personPtr := &amp;Person{name: <span class="hljs-string">"James Bond"</span>, age: <span class="hljs-number">32</span>}
    fmt.Println(personPtr)
    fmt.Println(*personPtr) <span class="hljs-comment">// Dereferencing the struct pointer</span>

    fmt.Printf(<span class="hljs-string">"Age of \"%v\" is \"%v\" \n"</span>, (*personPtr).name, (*personPtr).age)

    fmt.Println()
    <span class="hljs-comment">// Second way of creating pointer to struct</span>
    person := Person{name: <span class="hljs-string">"Jon Snow"</span>, age: <span class="hljs-number">24</span>}
    ptr := &amp;person
    fmt.Println(ptr)
    fmt.Println(*ptr) <span class="hljs-comment">// Dereferencing the struct pointer</span>

    fmt.Printf(<span class="hljs-string">"Age of \"%v\" is \"%v\" \n"</span>, (*ptr).name, (*ptr).age)
}
</code></pre>
<pre><code class="lang-go">&amp;{James Bond <span class="hljs-number">32</span>}
{James Bond <span class="hljs-number">32</span>}
Age of <span class="hljs-string">"James Bond"</span> is <span class="hljs-string">"32"</span> 

&amp;{Jon Snow <span class="hljs-number">24</span>}
{Jon Snow <span class="hljs-number">24</span>}
Age of <span class="hljs-string">"Jon Snow"</span> is <span class="hljs-string">"24"</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/lJYO7n5moq5"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above program, we're accessing the struct field by dereferencing the pointer <code>(*ptr).name, (*ptr).age</code> which reduces the readability and makes a program a little unkempt. The Golang also allow us to access fields of the struct without dereferencing the pointer as shown in the below example.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    name <span class="hljs-keyword">string</span>
    age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// First way of creating pointer to struct</span>
    person := &amp;Person{name: <span class="hljs-string">"James Bond"</span>, age: <span class="hljs-number">32</span>}
    fmt.Println(person)
    fmt.Printf(<span class="hljs-string">"Age of \"%v\" is \"%v\" \n"</span>, person.name, person.age)
}
</code></pre>
<pre><code class="lang-go">&amp;{James Bond <span class="hljs-number">32</span>}
Age of <span class="hljs-string">"James Bond"</span> is <span class="hljs-string">"32"</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/nYCTG9in-ws"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above program, we're accessing the field using <code>person.name, person.age</code>.</p>
<h2 id="heading-anonymous-struct-and-anonymous-fields">Anonymous Struct and anonymous fields</h2>
<h3 id="heading-anonymous-struct">Anonymous Struct</h3>
<p>In Golang we're allowed to create a struct without a name such a struct is called an anonymous struct. This kind of struct is useful if we want to use the struct only once in the program. We can create a struct using the following syntax:</p>
<pre><code class="lang-go">variable := <span class="hljs-keyword">struct</span>{
    <span class="hljs-comment">// field</span>
}{
    <span class="hljs-comment">// field value</span>
}

<span class="hljs-comment">// OR</span>

PtrVariable := &amp;<span class="hljs-keyword">struct</span>{
    <span class="hljs-comment">// field</span>
}{
    <span class="hljs-comment">// field value</span>
}
</code></pre>
<p>Below is an example of an anonymous struct.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    person := <span class="hljs-keyword">struct</span> {
        name <span class="hljs-keyword">string</span>
        age  <span class="hljs-keyword">int</span>
    }{
        name: <span class="hljs-string">"James Bond"</span>,
        age:  <span class="hljs-number">32</span>,
    }
    fmt.Println(person)

    ptrPerson := &amp;<span class="hljs-keyword">struct</span> {
        name <span class="hljs-keyword">string</span>
        age  <span class="hljs-keyword">int</span>
    }{
        name: <span class="hljs-string">"Jon Snow"</span>,
        age:  <span class="hljs-number">24</span>,
    }
    fmt.Println(ptrPerson)
}
</code></pre>
<pre><code class="lang-go">{James Bond <span class="hljs-number">32</span>}
&amp;{Jon Snow <span class="hljs-number">24</span>}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/1FQzainnKVs"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-anonymous-fields">Anonymous fields</h3>
<p>In Golang we're allowed to define anonymous fields in a struct. Anonymous fields are fields without a name. We just need to define the type of the field and Go will use that type as the name of that field. Below is the syntax of anonymous fields</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> structName <span class="hljs-keyword">struct</span>{
    <span class="hljs-comment">// value type</span>
    <span class="hljs-keyword">string</span>
    <span class="hljs-keyword">int</span>
    <span class="hljs-keyword">bool</span>
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    <span class="hljs-keyword">string</span>
    <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    person := &amp;Person{
        <span class="hljs-string">"James Bond"</span>, 
        <span class="hljs-number">32</span>,
    }
    fmt.Println(person)

    fmt.Printf(<span class="hljs-string">"Age of \"%v\" is \"%v\" \n"</span>, person.<span class="hljs-keyword">string</span>, person.<span class="hljs-keyword">int</span>)
}
</code></pre>
<pre><code class="lang-go">&amp;{James Bond <span class="hljs-number">32</span>}
Age of <span class="hljs-string">"James Bond"</span> is <span class="hljs-string">"32"</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/r5kNOoc1Xb5"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, we access the anonymous fields by using value type as the name of the field <code>person.string, person.int</code>.</p>
<p><strong><em>It is not allowed to define anonymous fields of the same type more than once.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Pointers in Go]]></title><description><![CDATA[The pointer is a special variable in Golang that stores the memory address of other variables.
Variables are used to store some type of data. All variables are assigned a particular memory where they store data and this memory has a memory address th...]]></description><link>https://pratikjagrut.space/pointers-in-go</link><guid isPermaLink="true">https://pratikjagrut.space/pointers-in-go</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[pointers]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Sat, 03 Sep 2022 22:05:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/gdMRXiTVMLI/upload/3dceecdbc544b63cfd755ff77119caa3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The pointer is a special variable in Golang that stores the memory address of other variables.</p>
<p>Variables are used to store some type of data. All variables are assigned a particular memory where they store data and this memory has a memory address that is in hexadecimal format. The number that starts with <code>0x</code> is hexadecimal like (<code>0x14</code> which is equivalent to 20 in decimal). Golang allows us to store this memory address in variables but only pointers will understand that the stored value is pointing to some memory whereas other variables will treat it just as a value.</p>
<h2 id="heading-declaring-pointer">Declaring Pointer</h2>
<p>The type <code>*T</code> is a pointer to a <code>T</code> value. Its zero value is <code>&lt;nil&gt;</code>.</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> pointer_name *Data_Type
<span class="hljs-keyword">var</span> p *<span class="hljs-keyword">int</span> = &amp;variable
</code></pre>
<p>In the above snippet, you can see two symbols <code>*</code> and <code>&amp;</code>, which are two operators.</p>
<p><code>* Operator</code> is also called dereferencing operator which is used to declare an operator and also to access the value stored at the memory address pointer pointing to.</p>
<p><code>&amp; Operator</code> this operator is used to access the memory address of a variable.</p>
<p>Below is an example demoing the use of * and &amp;.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  i := <span class="hljs-number">42</span>

  <span class="hljs-keyword">var</span> p *<span class="hljs-keyword">int</span> = &amp;i

  fmt.Println(<span class="hljs-string">"The value of i is: "</span>, *p)
  fmt.Println(<span class="hljs-string">"The memory address of i is"</span>, p)
}
</code></pre>
<pre><code class="lang-go">The value of i is:  <span class="hljs-number">42</span>
The memory address of i is <span class="hljs-number">0xc00002c008</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/DRmvVzN-gFK"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-shorthand-declaration">Shorthand Declaration</h3>
<p>In Golang shorthand declaration(:=) is used to narrow down the variable declaration. The Golang compiler will decide if the RHS variable is a pointer variable if we're assigning the memory address of the LHS variable using <code>&amp;</code>.</p>
<pre><code class="lang-go">i := <span class="hljs-number">42</span>
p := &amp;i
</code></pre>
<h3 id="heading-declaring-pointer-with-the-new-function">Declaring pointer with the new function</h3>
<p>Golang has a built-in allocating primitive function called <code>new</code>. The <code>new(T)</code> allocates memory, initializes it with a zero value of type T and returns the pointer to that memory. In Go terminology, it returns a pointer to a newly allocated zero value of type T.</p>
<p><strong>What is the difference between</strong> <code>var p *int</code> and <code>p := new(int)</code>?</p>
<p>The expression <code>var p *int</code> only declares the pointer and does not initialize it with any memory address, i.e pointer does not point to any memory location. Whereas in <code>new(T)</code> function returns the pointer pointing to the memory location in the system.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  <span class="hljs-keyword">var</span> p *<span class="hljs-keyword">int</span>
  fmt.Println(<span class="hljs-string">"The value of p"</span>, p)

  p1 := <span class="hljs-built_in">new</span>(<span class="hljs-keyword">int</span>)
  fmt.Println(<span class="hljs-string">"The value of *p1 is: "</span>, *p1)
  fmt.Println(<span class="hljs-string">"The value of p1"</span>, p1)
}
</code></pre>
<pre><code class="lang-go">The value of p &lt;<span class="hljs-literal">nil</span>&gt;
The value of *p1 is:  <span class="hljs-number">0</span>
The value of p1 <span class="hljs-number">0xc00002c008</span>
</code></pre>
<p>In the above example, we can not dereference the pointer <code>p</code> because it has <code>&lt;nil&gt;</code> value. Trying to dereference it will throw an error.</p>
<pre><code class="lang-go"><span class="hljs-built_in">panic</span>: runtime error: invalid memory address or <span class="hljs-literal">nil</span> pointer dereference
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/C8gmExWxJ5B"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h2 id="heading-passing-a-pointer-to-the-function">Passing a pointer to the function</h2>
<p>We can pass a pointer to the function as we pass other variables. We can create a pointer to the variable and then pass it to the function or we can just pass an address of that variable using <code>&amp;</code>.</p>
<p>In the below example, we initialize a variable i with the value 10. We have a function <code>addTen(i *int)</code> which takes a pointer as an argument and then adds 10 by dereferencing the pointer hence mutating the original value.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addTen</span><span class="hljs-params">(i *<span class="hljs-keyword">int</span>)</span></span> {
  *i = *i + <span class="hljs-number">10</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  i := <span class="hljs-number">10</span>
  p := &amp;i
  fmt.Println(i)
  addTen(p) <span class="hljs-comment">// Pass a pointer</span>
  fmt.Println(i)
  addTen(&amp;i) <span class="hljs-comment">// Pass address using &amp; operator</span>
  fmt.Println(i)
}
</code></pre>
<pre><code class="lang-go"><span class="hljs-number">10</span>
<span class="hljs-number">20</span>
<span class="hljs-number">30</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/gz-qxg5IT3Q"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h2 id="heading-pass-by-value-vs-pass-by-pointer">Pass-by-value vs Pass-by-pointer</h2>
<p>When we write a function we decide parameters to be passed <code>by-value</code> or <code>by-pointer</code>.</p>
<p><strong>Pass by value</strong></p>
<p>Every time variable is passed as a parameter a new copy of that variable is created and passed to the function. This copy has a different memory location hence any changes to this copy will not affect the original variable.</p>
<p>In the below example, we pass the parameter by value.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">add</span><span class="hljs-params">(i <span class="hljs-keyword">int</span>)</span></span> {
  i = i + <span class="hljs-number">10</span>
  fmt.Println(<span class="hljs-string">"Variable copy from add function:"</span>, i)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  i := <span class="hljs-number">10</span>
  fmt.Println(<span class="hljs-string">"Original variable:"</span>, i)
  add(i)
  fmt.Println(<span class="hljs-string">"Original variable:"</span>, i)
}
</code></pre>
<pre><code class="lang-go">Original variable: <span class="hljs-number">10</span>
Variable <span class="hljs-built_in">copy</span> from add function: <span class="hljs-number">20</span>
Original variable: <span class="hljs-number">10</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/uSHAuPe4dEn"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong>Pass by Pointer</strong></p>
<p>When we pass the parameter by-pointer Go makes a copy of that pointer to the new location. This pointer copy has the same memory address stored in it hence it is pointing to the original variable and any changes done using this pointer will change the value of the original variable.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">add</span><span class="hljs-params">(i *<span class="hljs-keyword">int</span>)</span></span> {
  *i = *i + <span class="hljs-number">10</span>
  fmt.Println(<span class="hljs-string">"Variable copy from add function:"</span>, *i)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  i := <span class="hljs-number">10</span>
  fmt.Println(<span class="hljs-string">"Original variable:"</span>, i)
  add(&amp;i)
  fmt.Println(<span class="hljs-string">"Original variable:"</span>, i)
}
</code></pre>
<pre><code class="lang-go">Original variable: <span class="hljs-number">10</span>
Variable <span class="hljs-built_in">copy</span> from add function: <span class="hljs-number">20</span>
Original variable: <span class="hljs-number">20</span>
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/ojMMRRkIeo3"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><em>In some way, we can say that pass-by-pointer is an implementation of pass-by-value.</em></p>
<h2 id="heading-container-typesslices-maps-etc-and-pointers">Container types(slices, maps etc) and pointers</h2>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">modify</span><span class="hljs-params">(h <span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span>)</span></span> {
    h[<span class="hljs-number">1</span>] = <span class="hljs-number">5</span>
    fmt.Println(<span class="hljs-string">"Modified map: "</span>, h)

}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    m := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">int</span>)
    m[<span class="hljs-number">1</span>] = <span class="hljs-number">1</span>
    m[<span class="hljs-number">2</span>] = <span class="hljs-number">2</span>
    m[<span class="hljs-number">3</span>] = <span class="hljs-number">3</span>
    fmt.Println(<span class="hljs-string">"Original map: "</span>, m)
    modify(m)
    fmt.Println(<span class="hljs-string">"Original map: "</span>, m)
}
</code></pre>
<p>In the above example, we're creating a map and passing it to the modify function. With the cursory look, it seems like we're passing an argument by-value because we're not passing the address of map m using &amp; or by creating a pointer to map m. So this means the copy of map m should be created and the original map is untouched. But if we run this we get an output as follows.</p>
<pre><code class="lang-go">Original <span class="hljs-keyword">map</span>:  <span class="hljs-keyword">map</span>[<span class="hljs-number">1</span>:<span class="hljs-number">1</span> <span class="hljs-number">2</span>:<span class="hljs-number">2</span> <span class="hljs-number">3</span>:<span class="hljs-number">3</span>]
Modified <span class="hljs-keyword">map</span>:  <span class="hljs-keyword">map</span>[<span class="hljs-number">1</span>:<span class="hljs-number">5</span> <span class="hljs-number">2</span>:<span class="hljs-number">2</span> <span class="hljs-number">3</span>:<span class="hljs-number">3</span>]
Original <span class="hljs-keyword">map</span>:  <span class="hljs-keyword">map</span>[<span class="hljs-number">1</span>:<span class="hljs-number">5</span> <span class="hljs-number">2</span>:<span class="hljs-number">2</span> <span class="hljs-number">3</span>:<span class="hljs-number">3</span>]
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/ORs5UkdECmS"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong><em>We passed an argument by value then why did the original map was updated?</em></strong></p>
<p>When we create a map using <code>m := make(map[int]int)</code> the compiler makes a call to the <code>runtime.makemap</code> a function whose signature is as <code>func makemap(t *maptype, hint int, h *hmap) *hmap</code>.</p>
<p>So as we see, the return type of <code>runtime.makemap</code> is a pointer to the <code>runtime.hmap structure</code>. So when we passed a map to the function we actually passed a pointer to the <code>runtime.hmap</code> structure of map m and hence the original map was modified.</p>
<p>Instead of mapping if we try the above program using slice we will get a similar output because the slice variable stores the pointer to an underlying array.</p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Closures in Go]]></title><description><![CDATA[Golang supports anonymous functions which are then used to form closure functions. Anonymous functions are functions without any name. Before going any further read about the anonymous function.
The closure is a special type of function value which r...]]></description><link>https://pratikjagrut.space/closures-in-go</link><guid isPermaLink="true">https://pratikjagrut.space/closures-in-go</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Closures]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Tue, 23 Aug 2022 21:57:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/maaWpQVgi00/upload/a4cb1578815bdf2fdaa963aa1379befa.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Golang supports anonymous functions which are then used to form closure functions. Anonymous functions are functions without any name. Before going any further read about the <strong><em>anonymous function</em></strong>.</p>
<p>The closure is a special type of function value which references a variable declared outside its body. The purpose of this function is to close over a variable of the upper function to form a closure. The function may access and assign to the referenced variables; in this sense, the function is "bound" to the variables.</p>
<p>Let's see an example. In this example, we create a closure which keeps track of the page hit or as a counter.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    hit := <span class="hljs-number">0</span>

    counter := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span> <span class="hljs-title">int</span></span> {
        hit += <span class="hljs-number">1</span>
        <span class="hljs-keyword">return</span> hit
    }

    fmt.Println(counter())
    fmt.Println(counter())
    fmt.Println(counter())
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/RT9Pm82Kf3p"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, we bound the closure to the <code>hit</code> variable which is not passed to it but accessed as a global variable.</p>
<p>The problem with the above code is, <code>hit</code> is a global variable. Hence another function has access to it. So any other operation can change the value of <code>hit</code>. To avoid this closure can isolate the data.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    counter := Counter()
    fmt.Println(counter())
    fmt.Println(counter())
    fmt.Println(counter())
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Counter</span><span class="hljs-params">()</span> <span class="hljs-title">func</span><span class="hljs-params">()</span> <span class="hljs-title">int</span></span> {
    hit := <span class="hljs-number">0</span>
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span> <span class="hljs-title">int</span></span> {
        hit++
        <span class="hljs-keyword">return</span> hit
    }
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/s5THHqJzD-Y"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>In the above example, closure is bound to or references to the <code>hit</code> variable which is still can be accessed after the function call. This means closure has access to the data and no other function has access to it hence this data can be tracked and isolated. This is one of the benefits of closure.</p>
<h2 id="heading-some-closure-use-cases">Some closure use cases</h2>
<h3 id="heading-isolating-the-data">Isolating the data</h3>
<p>Suppose we want to create a function that persists data after the functional call exists. For example, we create a Fibonacci series generator where we want to keep all variables away from the user's eye, so no one can manipulate it.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fibonacci</span><span class="hljs-params">()</span> <span class="hljs-title">func</span><span class="hljs-params">()</span> <span class="hljs-title">int</span></span> {
    n1 := <span class="hljs-number">0</span>
    n2 := <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span> <span class="hljs-title">int</span></span> {
        n1, n2 = n2, (n1 + n2)
        <span class="hljs-keyword">return</span> n1
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    f := fibonacci()
    fmt.Println(<span class="hljs-number">0</span>)
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10</span>; i++ {
        fmt.Println(f())
    }
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/hvidcU6RkeY"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-search-in-sorting-package">Search in sorting package</h3>
<p>A common use of Search is to find the index i for a value x in a sorted, indexable data structure such as an array or slice. In this case, the argument f, typically a closure, captures the value to be searched for, and how the data structure is indexed and ordered.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Search</span><span class="hljs-params">(n <span class="hljs-keyword">int</span>, f <span class="hljs-keyword">func</span>(<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">bool</span>) <span class="hljs-title">int</span></span>
</code></pre>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"sort"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    nums := []<span class="hljs-keyword">int</span>{<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span>, <span class="hljs-number">15</span>, <span class="hljs-number">21</span>, <span class="hljs-number">28</span>, <span class="hljs-number">36</span>, <span class="hljs-number">45</span>, <span class="hljs-number">55</span>}
    x := <span class="hljs-number">8</span>

    i := sort.Search(<span class="hljs-built_in">len</span>(nums), <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(i <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">bool</span></span> {
        <span class="hljs-keyword">return</span> nums[i] &gt;= x
    })
    fmt.Printf(<span class="hljs-string">"Index of %d is %d"</span>, x, i)
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/FQIjK3s6whR"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[Anonymous Functions in Go]]></title><description><![CDATA[The anonymous function is a feature in Golang which let us define a function without a name. This feature is also called a function literal. This is useful when you want an inline function or to form a closure.
Declaring the anonymous function
The sy...]]></description><link>https://pratikjagrut.space/anonymous-functions-in-go</link><guid isPermaLink="true">https://pratikjagrut.space/anonymous-functions-in-go</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[anonymous function]]></category><category><![CDATA[functions]]></category><dc:creator><![CDATA[Pratik Jagrut]]></dc:creator><pubDate>Fri, 19 Aug 2022 21:53:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/gnyA8vd3Otc/upload/88ce7d7ed12f617d1d0c6649c8b31ed2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The anonymous function is a feature in Golang which let us define a function without a name. This feature is also called a function literal. This is useful when you want an inline function or to form a closure.</p>
<h3 id="heading-declaring-the-anonymous-function">Declaring the anonymous function</h3>
<p>The syntax is pretty straightforward and much similar to normal function.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(parameter_list)</span><span class="hljs-params">(return_type)</span></span>{
  <span class="hljs-keyword">return</span>
}()
</code></pre>
<p><code>Parameter list</code> and <code>return type</code> are optional.</p>
<p><code>()</code> this will invoke the function as soon as it is defined.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        fmt.Println(<span class="hljs-string">"Golang Rocks!"</span>)
    }()
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/Kpnl__MXw7V"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-assigning-an-anonymous-function-to-a-variable">Assigning an anonymous function to a variable</h3>
<p>In Go, you can assign an anonymous function to a variable. The assigned variable will be of function type and it can be called as a regular function.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    v := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        fmt.Println(<span class="hljs-string">"Golang Rocks!"</span>)
    }
    fmt.Printf(<span class="hljs-string">"Type of variable v: %T\n"</span>, v)
    v()
}
</code></pre>
<pre><code class="lang-go">Type of variable v: <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span>
Golang Rocks!
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/Ebz_b0v-AX-"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-passing-an-argument-to-an-anonymous-function">Passing an argument to an anonymous function</h3>
<p>An anonymous function can take any number of arguments similar to a regular function.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(name <span class="hljs-keyword">string</span>)</span></span> {
        fmt.Println(<span class="hljs-string">"Hello, "</span>, name)
    }(<span class="hljs-string">"Jack"</span>)
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/oSsoVNXmNwX"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong>With any number of trailing arguments similar to Variadic functions</strong></p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(i ...<span class="hljs-keyword">int</span>)</span></span> {
        fmt.Println(i)
    }(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>)
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/vMjTAcWpKec"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong>Passing an anonymous function as an argument</strong></p>
<p>You can pass an anonymous function as an argument to a regular function or an anonymous function.</p>
<ul>
<li><em>Anonymous functions as an argument to a regular function</em></li>
</ul>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sayHello</span><span class="hljs-params">(af <span class="hljs-keyword">func</span>(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span>)</span> {
    fmt.Println(af(<span class="hljs-string">"Jack"</span>))
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {

    sayHello(<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + s
    })
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/UKJB3fh9DaA"><strong><em>Run this code in Go Playground</em></strong></a></p>
<ul>
<li><em>Anonymous function as an argument to an anonymous function</em></li>
</ul>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(v <span class="hljs-keyword">string</span>)</span></span> {
        fmt.Println(v)
    }(<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + s
    }(<span class="hljs-string">"Jack"</span>))
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/d8dprfgLXgF"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p>This above code looks a bit complicated and hard to fathom so another way we can achieve this is the following:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    af := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + s
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(af <span class="hljs-keyword">func</span>(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span>)</span> {
        fmt.Println(af(<span class="hljs-string">"Jack"</span>))
    }(af)
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/l7sP7Nz8qpw"><strong><em>Run this code in Go Playground</em></strong></a></p>
<h3 id="heading-return-an-anonymous-function-from-another-function">Return an anonymous function from another function</h3>
<p>We can return an anonymous function from another function</p>
<ul>
<li><em>Returning from regular function</em></li>
</ul>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sayHello</span><span class="hljs-params">()</span> <span class="hljs-title">func</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
    r := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + s
    }
    <span class="hljs-keyword">return</span> r
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    f := sayHello()
    fmt.Printf(<span class="hljs-string">"Type of variable f: %T\n"</span>, f)
    fmt.Println(f(<span class="hljs-string">"Jack"</span>))
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/NY3YiPG4N9h"><strong><em>Run this code in Go Playground</em></strong></a></p>
<ul>
<li><em>Returning from the anonymous function</em></li>
</ul>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    f := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span> <span class="hljs-title">func</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
        r := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> {
            <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + s
        }
        <span class="hljs-keyword">return</span> r
    }

    fmt.Printf(<span class="hljs-string">"Type of variable f: %T\n"</span>, f)
    c := f()

    fmt.Printf(<span class="hljs-string">"Type of variable c: %T\n"</span>, c)
    fmt.Println(c(<span class="hljs-string">"Jack"</span>))
}
</code></pre>
<p><a target="_blank" href="https://play.golang.org/p/jwfmOnhyOGh"><strong><em>Run this code in Go Playground</em></strong></a></p>
<p><strong><em>Thank you for reading this blog, and please give your feedback in the comment section below.</em></strong></p>
]]></content:encoded></item></channel></rss>