<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Geoffrey Sagini Mogambi</title>
    <description>The latest articles on DEV Community by Geoffrey Sagini Mogambi (@geoff89).</description>
    <link>https://dev.to/geoff89</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1091140%2F980e6495-c7aa-487d-850a-e57817f1c3c0.jpeg</url>
      <title>DEV Community: Geoffrey Sagini Mogambi</title>
      <link>https://dev.to/geoff89</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/geoff89"/>
    <language>en</language>
    <item>
      <title>Helm Charts: An Organised Way to Install Apps on a Kubernetes Cluster</title>
      <dc:creator>Geoffrey Sagini Mogambi</dc:creator>
      <pubDate>Mon, 27 Nov 2023 12:59:16 +0000</pubDate>
      <link>https://dev.to/geoff89/helm-charts-an-organised-way-to-install-apps-on-a-kubernetes-cluster-25i</link>
      <guid>https://dev.to/geoff89/helm-charts-an-organised-way-to-install-apps-on-a-kubernetes-cluster-25i</guid>
      <description>&lt;p&gt;Helm is a package manager for Kubernetes that helps in automating the deployment of applications in the Kubernetes cluster. Helm packages are called charts. A chart is a collection of related resources inside a directory that can deploy a variety of applications like databases, web applications, monitoring applications, machine learning applications and other related solutions to a Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;The charts can be downloaded from a repository and shared. A repository is a hub where Kubernetes packages are stored in the form of Helm charts. You can access these charts from &lt;a href="https://artifacthub.io/" rel="noopener noreferrer"&gt;ArtifactHub&lt;/a&gt; which is the repository containing the Helm packages. Once a chart is deployed in a Kubernetes cluster a release is created. A release is an instance of a chart running in the cluster and every time you install a chart a release is created.&lt;/p&gt;

&lt;p&gt;In this article, you will set up Helm and learn how to search, install, upgrade, do rollbacks, uninstall and manage chart releases. You will also create and package your own charts and set up your chart repositories that host charts that you want to install.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt; installed which will be used to run the Kubernetes cluster locally on your machine. To start Minikube run the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start --driver=virtualbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here Virtualbox is used as the driver of choice to start the minikube cluster. To use &lt;a href="https://www.virtualbox.org/wiki/Downloads" rel="noopener noreferrer"&gt;virtualbox&lt;/a&gt; ensure that it is installed. You can also use docker as a driver instead of VirtualBox. The Minikube command to use with the docker driver is &lt;code&gt;minikube start --driver=docker&lt;/code&gt;. Note that the &lt;a href="https://minikube.sigs.k8s.io/docs/drivers/" rel="noopener noreferrer"&gt;drivers&lt;/a&gt; which you can use with &lt;code&gt;minikube start&lt;/code&gt; are not just restricted to these two drivers demonstrated above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;Kubectl&lt;/a&gt; should also be installed. Luckily kubectl comes pre-installed with Minikube.&lt;/li&gt;
&lt;li&gt;Ensure you have &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;docker&lt;/a&gt; installed on your machine. Docker is a virtualization platform for shipping applications as containers.&lt;/li&gt;
&lt;li&gt;Basic knowledge of &lt;a href="https://docs.docker.com/get-started/overview/" rel="noopener noreferrer"&gt;docker&lt;/a&gt; and &lt;a href="https://kubernetes.io/docs/tutorials/kubernetes-basics/" rel="noopener noreferrer"&gt;kubernetes&lt;/a&gt; will be beneficial to follow this tutorial. 
To confirm if your local Kubernetes cluster is running use the following command.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An output similar to the following will be displayed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can test the connectivity of the cluster with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl cluster-info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything works fine there will be no errors and you are now connected to the local Kubernetes cluster. With the basic connection setup in place, it's time to install Helm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helm Installation
&lt;/h3&gt;

&lt;p&gt;In this section you will see how to install &lt;code&gt;helm&lt;/code&gt; on various &lt;code&gt;os&lt;/code&gt; platforms.&lt;/p&gt;

&lt;h4&gt;
  
  
  Installing Helm On Linux
&lt;/h4&gt;

&lt;p&gt;To install Helm in Linux use the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg &amp;gt; /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Installing Helm on macOS
&lt;/h4&gt;

&lt;p&gt;&lt;a href=""&gt;Homebrew&lt;/a&gt; package manager for macOS will be used to install Helm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Installing Helm on Windows
&lt;/h4&gt;

&lt;p&gt;Type the following commands on the Windows terminal to install helm. You can use either &lt;a href="https://scoop.sh/#/" rel="noopener noreferrer"&gt;Scoop&lt;/a&gt; a command-line installer for Windows or &lt;a href="https://chocolatey.org/" rel="noopener noreferrer"&gt;Chocolatey&lt;/a&gt; which is a Package Manager for Windows to install helm.&lt;/p&gt;

&lt;h5&gt;
  
  
  Installing with Scoop
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scoop install helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Installing with Chocolately
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;choco install kubernetes-helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm if Helm is installed type &lt;code&gt;helm&lt;/code&gt; on the terminal and an output displaying various helper commands from helm will be displayed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Searching Helm  Charts from a Chart Repository
&lt;/h3&gt;

&lt;p&gt;Helm charts are stored in a chart repository. This repository analogy is similar to &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;docker hub&lt;/a&gt; where you can pull or push images. In a chart repository, you can also pull your charts from the repository and update the repository locally for you to use the chart.&lt;br&gt;
The repository that hosts  Helm charts is &lt;a href="https://artifacthub.io/" rel="noopener noreferrer"&gt;ArtifactHub&lt;/a&gt;.  ArtifactHub is a web based application that enables finding, installing and publishing Kubernetes packages and configurations. &lt;br&gt;
Searching for the helm charts can be done in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Through the terminal.&lt;/li&gt;
&lt;li&gt;Through the artifacthub graphical user interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's search for one of the most commonly used charts in DevOps which is &lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt;. Grafana is an interactive data visualization platform that provides charts that are put into dashboards from which insights from complex infrastructure can be analyzed. You can also query and set alerts based on the set criteria for metrics on the supported integrated data sources with grafana. Searching grafana helm chart via the terminal can be done with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm search hub grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will display a list of grafana charts from which you can choose from.&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu54kp12m11su7iv5pf2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu54kp12m11su7iv5pf2y.png" alt="Image description" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also search the &lt;code&gt;Grafana&lt;/code&gt; chart via the artifacthub homepage and all the indexed charts related to grafana will be displayed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb3s4wbkepn3cpgycazg4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb3s4wbkepn3cpgycazg4.png" alt="Image description" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A list of available grafana charts will be displayed from which you can choose the one you want to use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zw8im2a9f7v9jarql05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zw8im2a9f7v9jarql05.png" alt="Image description" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Helm charts in ArtifactHub have instructions on how to install the charts on the cluster. Select the first grafana chart displayed on the results list and click the install button shown on the right side of the page. A pop-up with the installation instructions will be displayed as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lcz68q9ivs8jhjbrp6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lcz68q9ivs8jhjbrp6o.png" alt="Image description" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can copy the instructions at the terminal to add the grafana repository of the grafana helm chart to the cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add grafana https://grafana.github.io/helm-charts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"grafana" has been added to your repositories
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the repo has been added let Helm know it exists by doing an update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "grafana" chart repository
Update Complete. ⎈Happy Helming!⎈
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having done the above, the next step is to install the Helm chart.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helm Chart Installation
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;grafana&lt;/code&gt; chart repo added in the previous section contains configuration variables that can be modified if you want to upgrade or do a rollback of a release. The values are stored in &lt;code&gt;values.yaml&lt;/code&gt; file and can be viewed with the command &lt;code&gt;helm show values chartname&lt;/code&gt;. The chartname in your case is &lt;code&gt;(repository/chartname)&lt;/code&gt; which is &lt;code&gt;grafana/grafana&lt;/code&gt; as shown in the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; helm show values grafana/grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A long output of the values stored in the &lt;code&gt;values.yaml&lt;/code&gt; file for grafana chart will be displayed. To install the grafana helm chart, &lt;code&gt;helm install&lt;/code&gt; command is used with the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; helm install releasename repository/chartname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your instance replace the above command with the following values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install grafana grafana/grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The displayed output will be similar to the following:&lt;/p&gt;

&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME: grafana
LAST DEPLOYED: Tue Nov 21 23:53:13 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get your 'admin' user password by running:
   kubectl get secret --namespace default grafana -o 
   jsonpath="{.data.admin-password}" | base64 --decode ; echo
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output displayed has a &lt;code&gt;NAME&lt;/code&gt; which is the name of your release &lt;code&gt;grafana&lt;/code&gt;. Other metadata information include &lt;code&gt;namespace&lt;/code&gt;, &lt;code&gt;revision&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;deployment date&lt;/code&gt; of when the helm chart was installed. The &lt;code&gt;NOTES&lt;/code&gt; section contains instructions of how to implement the installed chart and access to it.&lt;br&gt;
To review the deployed charts use &lt;code&gt;helm list&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME    NAMESPACE   REVISION    UPDATED                                 STATUS      CHART           APP VERSION
grafana default     1           2023-11-21 23:53:13.531164235 +0300 EAT deployed    grafana-7.0.8   10.1.5     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To view if the installed grafana release is working, run the command below to see the pods running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                   READY   STATUS      RESTARTS   AGE
grafana-f4bf7955b-6lzbn                1/1     Running     0          63m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also view all Kubernetes resource components by using the command &lt;code&gt;kubectl get all&lt;/code&gt; which will show resources like &lt;code&gt;pods&lt;/code&gt;, &lt;code&gt;deployments&lt;/code&gt;, &lt;code&gt;services&lt;/code&gt; and &lt;code&gt;replicasets&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Upgrading a Helm Release
&lt;/h3&gt;

&lt;p&gt;With the deployed release now in place, you may want to modify the release to handle more traffic by increasing the number of &lt;code&gt;pods&lt;/code&gt; running in the cluster. For this to be done you will have to do an upgrade of the deployed release. At this point, you may ponder whether you have to uninstall the release and redeploy it afresh again with the new changes. The good thing for you is that is not necessary. You can use &lt;code&gt;helm upgrade&lt;/code&gt; command to upgrade the release and a new version of the chart will be created.&lt;br&gt;
The grafana chart has a configuration known as replicas that control the number of deployed pods. Currently, one pod is running in the cluster. To confirm the pod running, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                   READY   STATUS      RESTARTS   AGE
grafana-f4bf7955b-6lzbn                1/1     Running     0          63m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above, you can see the pod that is running is one as shown in the &lt;code&gt;READY&lt;/code&gt; column with &lt;code&gt;1/1&lt;/code&gt;. What if you want to implement redundancy in your system to prevent failure in case one of the pods is not running properly? Redundancy in such a scenario can be achieved by adding more pods. Set the configuration variable &lt;code&gt;replicas&lt;/code&gt; of the grafana chart to use &lt;code&gt;3 pods&lt;/code&gt; with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm upgrade grafana  grafana/grafana --set replicas=3 --reuse-values
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--reuse-values&lt;/code&gt; flag instructs helm to merge the new value set with the old values. This means the old values are added on top of the previous release. The updated release will look like the one below:&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Release "grafana" has been upgraded. Happy Helming!
NAME: grafana
LAST DEPLOYED: Wed Nov 22 01:03:28 2023
NAMESPACE: default
STATUS: deployed
REVISION: 2
NOTES:
1. Get your 'admin' user password by running:

   kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To view whether the pods running are three in number after upgrading, run the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                   READY   STATUS      RESTARTS   AGE
grafana-564c5b7d4b-b7fjh               1/1     Running     0          116s
grafana-564c5b7d4b-p9dgq               1/1     Running     0          2m7s
grafana-564c5b7d4b-z4h5j               1/1     Running     0          2m18s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above results, you can see three grafana pods are now running after upgrading the release. You can now test the grafana dashboard chart in the browser to see if it is running on the Kubernetes cluster.  Start by getting the password you will use to login in with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lengthy string containing the password will be shown. Keep it somewhere safe as you will need it for login. Next is to get the Grafana URL by running the following commands at the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=grafana" -o jsonpath="{.items[0].metadata.name}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Proceed to use the &lt;code&gt;POD_NAME&lt;/code&gt; variable with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl --namespace default port-forward $POD_NAME 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output at the terminal will display results similar to the one below after doing a port-forward:&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Forwarding from 127.0.0.1:3000 -&amp;gt; 3000
Forwarding from [::1]:3000 -&amp;gt; 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to the browser of your choice and paste &lt;code&gt;127.0.0.1:3000&lt;/code&gt; and a graphical user interface to login to grafana will be displayed as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhdu1vbtyed5bpdgv0bp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhdu1vbtyed5bpdgv0bp.png" alt="Image description" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To login use &lt;code&gt;admin&lt;/code&gt; as the username and for the password field copy the string of password you earlier got when you ran the &lt;code&gt;kubectl get secret ...&lt;/code&gt; command. When logged in, the dashboard will appear like the one below and you can now explore the grafana dashboard features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwex3valy9f76aeogcjxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwex3valy9f76aeogcjxl.png" alt="Image description" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this in place, the next step is to do rollback changes and delete the release.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementing a Rollback and Deleting a Release
&lt;/h4&gt;

&lt;p&gt;When you do a Helm Upgrade on a release, a new version is created in an incremental manner. Helm stores all the revisions of a release internally which allows you to return to a previous revision if needed. In your scenario, you want to revert back to one pod from the current three pods running. The &lt;code&gt;helm rollback release_name release_version&lt;/code&gt; command will be used for the revision. To do a rollback to &lt;code&gt;revision 1&lt;/code&gt; which is the state where you had one pod run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm rollback grafana 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output you get will show the rollback is successful as shown below.&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rollback was a success! Happy Helming!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check the revised revision by listing the releases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new revision is &lt;code&gt;3&lt;/code&gt; and not &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME    NAMESPACE   REVISION    UPDATED                                 STATUS      CHART           APP VERSION
grafana default     3           2023-11-22 01:15:42.462861105 +0300 EAT deployed    grafana-7.0.8   10.1.5     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In every change whether an upgrade or rollback of a release, helm will create a new revision. In your case, the revision will be &lt;code&gt;3&lt;/code&gt; but still will be similar to revision &lt;code&gt;1&lt;/code&gt; which has one pod. You can confirm this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output below will show one pod running in your grafana release.&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                                   READY   STATUS      RESTARTS   AGE
grafana-f4bf7955b-bl5rw                1/1     Running     0          2m30s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To delete a release and associated revisions use &lt;code&gt;helm delete release_name&lt;/code&gt; command. The following command will delete the grafana release in the cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm delete grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will display results stating that grafana has been uninstalled:&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;release "grafana" uninstalled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now confirm if the release has been deleted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output displayed will show no release list available:&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploying Custom Charts
&lt;/h3&gt;

&lt;p&gt;In this section you are going to deploy your own custom helm charts. Use the following command to create a custom chart named &lt;code&gt;kubechart&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm create kubechart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A new directory with the name of the chart will be created. To view the contents of the chart created use the &lt;code&gt;tree&lt;/code&gt; command at the root of the project where the chart has been created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
└── kubechart
    ├── charts
    ├── Chart.yaml
    ├── templates
    │   ├── deployment.yaml
    │   ├── _helpers.tpl
    │   ├── hpa.yaml
    │   ├── ingress.yaml
    │   ├── NOTES.txt
    │   ├── serviceaccount.yaml
    │   ├── service.yaml
    │   └── tests
    │       └── test-connection.yaml
    └── values.yaml

4 directories, 10 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is a brief overview of the above folder structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;charts&lt;/code&gt;: charts is a directory that contains other charts called subcharts. At the moment it's empty but as your business needs grow subcharts can be placed inside this folder.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Chart.yaml&lt;/code&gt;: This is where the metadata information related to your chart will reside. This includes information like API version of the chart, name and description of the project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;templates&lt;/code&gt;: This directory contains all resource definitions that your chart will install on the cluster.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;values.yaml&lt;/code&gt;: This file contains the default values for the chart. These values can be overridden when using &lt;code&gt;helm install&lt;/code&gt; or &lt;code&gt;helm upgrade&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can now install the created custom chart. The created custom chart you are using contains the default &lt;code&gt;nginx&lt;/code&gt; image for demonstration purposes but you can follow these exact steps when using your own images. In the &lt;code&gt;helm install&lt;/code&gt; command pass flags &lt;code&gt;--dry-run&lt;/code&gt; and &lt;code&gt;--debug&lt;/code&gt; while pointing to the current chart directory to see what helm would deploy to the cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install kubechart --dry-run --debug ./kubechart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lengthy output will be displayed and will contain all the resource definitions to be applied to your cluster. You can now go ahead to package the chart for distribution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm package ./kubechart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated output will be similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Successfully packaged chart and saved it to: .../kubechart-0.1.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now go ahead to install the packaged chart. The installation process is similar to how you install charts from the artifacthub repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install kubechart kubechart-0.1.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will contain a set of instructions that you can use to run your chart.&lt;/p&gt;

&lt;h5&gt;
  
  
  output
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME: kubechart
LAST DEPLOYED: Fri Nov 24 16:25:08 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=kubechart,app.kubernetes.io/instance=kubechart" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have now successfully deployed your custom chart running nginx.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;You now know how to use helm charts to install, upgrade, do rollbacks and uninstall helm releases on your Kubernetes cluster. You have also seen how to use the ArtifactHub chart repository to get helm charts. You have also seen how to create your own custom charts by installing and packaging the charts. &lt;br&gt;
For further guidance regarding helm charts visit &lt;a href="https://helm.sh/docs/chart_template_guide/getting_started/" rel="noopener noreferrer"&gt;official helm page&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>helm</category>
    </item>
    <item>
      <title>How to Deploy PostgreSQL with Docker and Docker Compose</title>
      <dc:creator>Geoffrey Sagini Mogambi</dc:creator>
      <pubDate>Wed, 15 Nov 2023 08:57:49 +0000</pubDate>
      <link>https://dev.to/geoff89/how-to-deploy-postgresql-with-docker-and-docker-compose-3lj3</link>
      <guid>https://dev.to/geoff89/how-to-deploy-postgresql-with-docker-and-docker-compose-3lj3</guid>
      <description>&lt;p&gt;In this article you will learn how to deploy &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; with &lt;a href="https://docs.docker.com/get-started/overview/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; and &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;. Postgres is a free, open source and advanced database management system that supports both SQL(relational) and JSON(non-relational) querying. Docker on the other hand is an open platform used for developing, shipping and running applications as containers. Docker applications can be run on any platform once the image has been build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt;Prerequisites&lt;br&gt;
Deploying PostgreSQL with Docker&lt;br&gt;
Deploying PostgreSQL with Docker Compose&lt;br&gt;
Conclusion&lt;/p&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before delving further into this article the following requirements will be beneficial to have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basic knowledge of docker and its commands.&lt;/li&gt;
&lt;li&gt;Familiarity with docker compose will come in handy.&lt;/li&gt;
&lt;li&gt;An Understanding of how relational databases like 
PostgreSQL work.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Deploying PostgreSQL with Docker
&lt;/h3&gt;

&lt;p&gt;The first approach you are going to use in deploying Postgres is searching the Postgres image from docker hub. You will then launch a Postgres container from the image pulled from &lt;a href="https://hub.docker.com/_/postgres" rel="noopener noreferrer"&gt;docker hub&lt;/a&gt;.&lt;br&gt;
Begin by searching the Postgres image from the Docker Registry with the following command at the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker search postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of the displayed available Postgres images from Docker hub should be similar to the one below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt1zfiwjcazsuhpd5ywm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt1zfiwjcazsuhpd5ywm.png" alt="Image description" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having done the above you can go ahead to pull the latest PostgreSQL image with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull postgres:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An output similar to the following pulling the latest Postgres image from the Docker hub will be observed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45knhfmuew7oxbfcizpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45knhfmuew7oxbfcizpn.png" alt="Image description" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can verify the downloaded image with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it's time to run your container from the downloaded Postgres image. To run the container execute the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name postgres-container -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -p 5432:5432 -d postgres 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through the above command that is used to create your container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You start by stating the name of the container which is postgres-container from the --name tag.&lt;/li&gt;
&lt;li&gt;The Postgres user will be root from the environment variable &lt;code&gt;POSTGRES_USER&lt;/code&gt; and password will be secret from the environment variable &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Next you create a port mapping by binding the host network followed by a colon and then the corresponding container network with the -p tag. The port value 5432 used here is the same for both our host and container network but a different port number can still be used for both host and container network.&lt;/li&gt;
&lt;li&gt;Finally you state Postgres as the name of the image which will use the latest image tag pulled from the docker hub.
You can go ahead to press enter and Docker will start the Postgres container returning a long unique ID. To view all running containers use the &lt;code&gt;docker ps&lt;/code&gt; command. The output of the above steps will be displayed as below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8ojv4hgg1qnxdghexk4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8ojv4hgg1qnxdghexk4.png" alt="Image description" width="800" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Postgres server is now ready to accept incoming connections. To execute it, use the &lt;code&gt;docker exec&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it postgres-container psql -U root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command instructions are explained below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The -it flag instructs docker to run the command as an interactive TTY session. Afterward, you specify the name of the container which is &lt;code&gt;postgres-container&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can now run psql command to access the Postgres console. Use the &lt;code&gt;-U&lt;/code&gt; flag to tell &lt;code&gt;psql&lt;/code&gt; that you want to connect as root user.&lt;/li&gt;
&lt;li&gt;And just like that you are inside the Postgres server and you can now create a database, table or do any administrative task required of Postgres server. A display similar to the following will be shown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyw26i5cvaiayh5fcudz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyw26i5cvaiayh5fcudz.png" alt="Image description" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To exit from the Postgres server just type \q in the shell inside the Postgres server as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root=# \q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, you have seen how to use Postgres with docker in the terminal. In the next section let's see how to deploy Postgres with an even better approach that is neater which is docker compose. &lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying PostgreSQL with Docker Compose
&lt;/h3&gt;

&lt;p&gt;To deploy Postgres with docker compose you will have to write a docker compose yaml file. All the steps will be in a single &lt;code&gt;YAML&lt;/code&gt; file making it neat and clear to follow the steps of pulling the Postgres image and running it as a container.&lt;br&gt;
To create the &lt;code&gt;yaml&lt;/code&gt; file just type the following at the terminal in a folder of your choice to create the docker compose yaml file.&lt;/p&gt;

&lt;p&gt;Create a folder where your &lt;code&gt;yaml&lt;/code&gt; file will reside. At the terminal type the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ~/docker-compose-pg &amp;amp;&amp;amp; cd ~/docker-compose-pg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then create your docker-compose file as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch docker-compose-pg.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the docker-compose-pg.yaml file, type the following in the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.8"
services:
  postgres:
    image: postgres:14-alpine
    restart: always
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=secret
    ports:
      - "5432:5432"
    volumes:
     - db:/var/lib/postgresql/data
volumes:
  db: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The created docker compose file has the following contents:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It uses the docker-compose file of &lt;a href="https://docs.docker.com/compose/compose-file/compose-file-v3/#service-configuration-reference" rel="noopener noreferrer"&gt;version 3.8&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Next you create a service named Postgres. A service is analogous to &lt;code&gt;docker run&lt;/code&gt; when you want to run a container from an image.&lt;/li&gt;
&lt;li&gt;The docker-compose file will use the postgres:14-alpine image from docker hub and will restart automatically if the container stops.&lt;/li&gt;
&lt;li&gt;The next step is to define the environment variables. In your case, you define the Postgres user and password to be used when executing the Postgres database. To learn more about environment variables you can refer to &lt;a href="https://docs.docker.com/compose/environment-variables/set-environment-variables/" rel="noopener noreferrer"&gt;docker-compose environment guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The next step is to map the host port 5432 to the container port 5432 as Postgres will run in that port in the container.&lt;/li&gt;
&lt;li&gt;The last part of your docker-compose is to manage the &lt;a href="https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes" rel="noopener noreferrer"&gt;volume&lt;/a&gt; which is named db. Volumes help in persisting the data during the lifetime of the container or should the container restart. To show volumes attached to your Postgres container just type &lt;code&gt;docker volume ls&lt;/code&gt; and &lt;code&gt;docker volume inspect&lt;/code&gt; to get the volume information.
You are now ready to start your Postgres container. Type the following command on the terminal.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose -f docker-compose-pg.yaml up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will start the Postgres container in the background and leave it running. Since your file has a different name from the default (docker-compose.yaml) file you will need to use the &lt;code&gt;-f&lt;/code&gt; flag and then specify the name of your docker compose file which is docker-compose-pg.yaml.&lt;br&gt;
The output will be similar to the following after running the command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4y5l5zltcv9ey77a4o28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4y5l5zltcv9ey77a4o28.png" alt="Image description" width="800" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To confirm that our container is running use the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output should show you the name of the container as below which is postgresyaml-postgres-1. One thing to note is if you don't state the &lt;code&gt;container_name&lt;/code&gt; inside the docker compose file, after the creation of the container, docker compose will assign the container name with the name of the location where your docker compose file is. In your case since the docker compose file &lt;code&gt;docker-compose-pg.yaml&lt;/code&gt; lies in folder &lt;code&gt;postgresyaml&lt;/code&gt; then the container name will contain the name of the folder combined with the service name and &lt;code&gt;1&lt;/code&gt; appended to the name at the end. The name of the container will become &lt;code&gt;postgresyaml-postgres-1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts4hlg6zy8p9frod0f26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts4hlg6zy8p9frod0f26.png" alt="Image description" width="800" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now it's time to execute your container in the terminal and use the Postgres server. The docker command to use is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it postgresyaml-postgres-1 psql -U root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voila you are inside the Postgres server. You can type the following &lt;code&gt;SQL&lt;/code&gt; commands in &lt;code&gt;psql&lt;/code&gt; terminal to see the current timestamp and date. For the current timestamp type &lt;code&gt;select now();&lt;/code&gt; and for the date &lt;code&gt;select current_date;&lt;/code&gt;. The display will be as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyfn4fnup6mjeckxf0ex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyfn4fnup6mjeckxf0ex.png" alt="Image description" width="800" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The setup is now complete and you can exit the Postgres server by using the &lt;code&gt;q&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this post, you learned how to deploy Postgres with docker and docker-compose. You first began by pulling the Postgres image from the docker hub. From the pulled image you deployed the Postgres container. A similar process was done with docker compose but in a cleaner approach which put all the container configurations in a yaml file. You can now deploy Postgres with both docker and docker compose.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>postgres</category>
      <category>sql</category>
    </item>
    <item>
      <title>Metaprogramming in Golang: Reflection Package guide</title>
      <dc:creator>Geoffrey Sagini Mogambi</dc:creator>
      <pubDate>Wed, 15 Nov 2023 08:41:59 +0000</pubDate>
      <link>https://dev.to/geoff89/metaprogramming-in-golang-reflection-package-guide-41bp</link>
      <guid>https://dev.to/geoff89/metaprogramming-in-golang-reflection-package-guide-41bp</guid>
      <description>&lt;p&gt;Reflection package is a very important feature in Golang because it allows metaprogramming, which is the capability of an application to examine its own structure. It works with types and it's used to analyze types at runtime. Types, Values and Kinds are the foundation of the reflect package. The reflection package allows you to extract the type and value from any &lt;code&gt;interface{}&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Let's implement the reflection package with examples. &lt;/p&gt;

&lt;h3&gt;
  
  
  reflect.TypeOf()
&lt;/h3&gt;

&lt;p&gt;The TypeOf function is used to describe the &lt;code&gt;reflect.type&lt;/code&gt; value that is passed into the TypeOf method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    var1 := "Reflection Package"
    fmt.Println(reflect.TypeOf(var1))

    var2 := 100
    fmt.Println(reflect.TypeOf(var2))

    var3 := true
    fmt.Println(reflect.TypeOf(var3))

    var4 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    fmt.Println(reflect.TypeOf(var4))

    var5 := map[string]interface{}{"Name": "Paul", "Number": 1000}
    fmt.Println(reflect.TypeOf(var5))
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string
int
bool
[]int
map[string]interface {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will show the various data types representation assigned by the variable. If the variable assigned is a string, the typeOf will be a string. If it is a Map variable the typeOf will show type Map and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  reflect.Value()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;reflect.value&lt;/code&gt; is used to show the underlying value of the respective variable passed to &lt;code&gt;reflect.ValueOf&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    var1 := "Reflection Package"
    fmt.Println(reflect.ValueOf(var1))

    var2 := 100
    fmt.Println(reflect.ValueOf(var2))

    var3 := true
    fmt.Println(reflect.ValueOf(var3))
    fmt.Println(reflect.ValueOf(&amp;amp;var3))

    var4 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    fmt.Println(reflect.ValueOf(var4))

    var5 := map[string]interface{}{"Name": "Paul", "Number": 1000}
    fmt.Println(reflect.ValueOf(var5))
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reflection Package
100
true
0xc00001a0c0
[1 2 3 4 5 6 7 8 9 10]
map[Name:Paul Number:1000]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.Kind()
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Kind&lt;/code&gt; is a property of &lt;code&gt;reflect.Type&lt;/code&gt; whose results display basic types and generic complex types. When using kind, for built in types &lt;code&gt;Kind&lt;/code&gt; and &lt;code&gt;Type&lt;/code&gt; will be the same but for the custom types they will differ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    var1 := "Reflection Package"
    fmt.Println(reflect.TypeOf(var1).Kind())

    var2 := 100
    fmt.Println(reflect.TypeOf(var2).Kind())

    var3 := true
    fmt.Println(reflect.TypeOf(var3).Kind())

    var4 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    fmt.Println(reflect.TypeOf(var4).Kind())

    var5 := map[string]interface{}{"Name": "Paul", "Number": 1000}
    fmt.Println(reflect.TypeOf(var5).Kind())
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string
int
bool
slice
map
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.Copy()
&lt;/h3&gt;

&lt;p&gt;The copy method will copy contents from the source to the destination until either the source has been exhausted or the destination has been filled. Both Source and Destination must have a kind of slice or array and the elements in the slice or array must be of the same type. If the source has elements of string type the equivalent type of string should also be used in the destination. The same scenario will be applied to other types like boolean, integers, floats, and any other type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    source := reflect.ValueOf([]int{1, 2, 3, 4})
    destination := reflect.ValueOf([]int{5, 6, 7, 8})

    // Copy() function retuns number of elements copied
    counter := reflect.Copy(destination, source)

    fmt.Println(counter)
    fmt.Println(source)
    fmt.Println(destination)
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4
[1 2 3 4]
[1 2 3 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.DeepEqual()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;DeepEqual&lt;/code&gt; method will return either True or False if the value in your case X and Y types follow the following rules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Array values are deeply equal if their corresponding elements are deeply equal.&lt;/li&gt;
&lt;li&gt;Struct values are deeply equal if their corresponding fields both exported and unexported are deeply equal.&lt;/li&gt;
&lt;li&gt;Func values are deeply equal if both are nil otherwise they are not deeply equal.&lt;/li&gt;
&lt;li&gt;Interface values will be said to be deeply equal if they hold equal concrete deep values.&lt;/li&gt;
&lt;li&gt;For Map values deep equal applies when all of the following is true; they are both nil or both are non nil, they have the same length and either of them has the same Map object or corresponding Keys (matched using GO equality) map to deeply equal values.&lt;/li&gt;
&lt;li&gt;Pointer values are deeply equal if using &lt;code&gt;==&lt;/code&gt; operator shows equality or if they point to deeply equal values.&lt;/li&gt;
&lt;li&gt;Slice values are deep equal when they have the same length and both are nil or non nil.&lt;/li&gt;
&lt;li&gt;For other type values like strings, bools, numbers and channels they are deeply equal if using &lt;code&gt;==&lt;/code&gt; operator shows equality.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

type Employee struct {
    name    string
    address int
    email   string
}

func main() {
    // DeepEqual checks whether slices are are equal
    slice1 := []string{"a", "b", "c", "d"}
    slice2 := []string{"g", "h", "i", "j"}
    result := reflect.DeepEqual(slice1, slice2)
    fmt.Println(result)

    slice3 := []string{"a", "b", "c", "d"}
    slice4 := []string{"a", "b", "c", "d"}
    result2 := reflect.DeepEqual(slice3, slice4)
    fmt.Println(result2)

    // DeepEqual will check whether the arrays are equal
    arr1 := [3]int{10, 20, 30}
    arr2 := [3]int{10, 20, 30}
    result = reflect.DeepEqual(arr1, arr2)
    fmt.Println(result)

    // DeepEqual will check whether the structs are equal
    emp1 := Employee{"Sagini", 10259, "sagini@gmail"}
    emp2 := Employee{"Kamau", 6789, "kamau@gmail"}
    result = reflect.DeepEqual(emp1, emp2)
    fmt.Println(result)
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;false
true
true
false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.Swapper()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Swapper&lt;/code&gt; method is used to swap elements in a given slice and will throw a panic should the underlying &lt;code&gt;interface{}&lt;/code&gt; provided not be a slice. Indexes of the respective values are used to do the swap.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    swapSlice := []int{1, 2, 3, 4, 5, 6, 7}
    swap := reflect.Swapper(swapSlice)
    fmt.Printf("Original slice is :%v\n", swapSlice)

    // Swapper() function swaps elements in the provided slice using their index
    swap(1, 6)
    fmt.Printf("After the swap slice is :%v\n", swapSlice)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original slice is :[1 2 3 4 5 6 7]
After the swap slice is :[1 7 3 4 5 6 2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.NumField()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;NumField&lt;/code&gt; method returns the number of fields in a given struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

type Employee struct {
    Name    string
    Address int
    Email   string
}

func main() {
    emp := Employee{"Geoffrey", 675757, "geoff@yahoo"}
    empType := reflect.TypeOf(emp)
    fmt.Println(empType.NumField())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.Field()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Field&lt;/code&gt; method returns the &lt;code&gt;reflect.value&lt;/code&gt; of the field that is name of the field accessed and it's type at the specified index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

type Employee struct {
    Name    string
    Address int
    Email   string
}

func main() {
    emp := Employee{"Geoffrey", 675757, "geoff@yahoo"}
    empType := reflect.TypeOf(emp)

    // create a loop to loop over the struct
    for i := 0; i &amp;lt; empType.NumField(); i++ {
        field := empType.Field(i)
        fmt.Println(field.Index, field.Name, field.Type)
    }

}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0] Name string
[1] Address int
[2] Email string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.FieldByName()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;FieldByName&lt;/code&gt; method is used to either get or set a struct field value by using name of a given field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

type Address struct {
    Latitude  int
    Longitude int
    Places    string
}

func main() {
    addr := Address{10, 30, "HeavensPark"}
    fmt.Println(reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Latitude"))
    fmt.Println(reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Longitude"))
    fmt.Println(reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Places"))

    reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Latitude").SetInt(20)
    reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Longitude").SetInt(40)
    reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Places").SetString("TreeTops")

    fmt.Println(reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Latitude"))
    fmt.Println(reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Longitude"))
    fmt.Println(reflect.ValueOf(&amp;amp;addr).Elem().FieldByName("Places"))
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10
30
HeavensPark
20
40
TreeTops
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.FieldByIndex()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;FieldByIndex&lt;/code&gt; method will return a nested field corresponding to an index. A panic will occur if during the evaluation of struct, it finds a  nil pointer or a field that is not a struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    firstName string
    lastName  string
}

type Account struct {
    Person
    accountName string
}

func main() {
    acc := Account{
        Person:      Person{"Sagini", "Geoffrey"},
        accountName: "Stanchart",
    }
    t := reflect.TypeOf(acc)

    fmt.Printf("%#v\n", t.FieldByIndex([]int{0}))
    fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 0}))
    fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 1}))
    fmt.Printf("%#v\n", t.FieldByIndex([]int{1}))
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reflect.StructField{Name:"Person", PkgPath:"", Type:(*reflect.rtype)(0x490ba0), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true}
reflect.StructField{Name:"firstName", PkgPath:"main", Type:(*reflect.rtype)(0x48b4c0), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false}
reflect.StructField{Name:"lastName", PkgPath:"main", Type:(*reflect.rtype)(0x48b4c0), Tag:"", Offset:0x10, Index:[]int{1}, Anonymous:false}
reflect.StructField{Name:"accountName", PkgPath:"main", Type:(*reflect.rtype)(0x48b4c0), Tag:"", Offset:0x20, Index:[]int{1}, Anonymous:false}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.MakeSlice()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;MakeSlice&lt;/code&gt; method creates a new slice value. From the created slice you can find its type, length and capacity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    var intSlice []int
    var intType reflect.Value = reflect.ValueOf(&amp;amp;intSlice)
    createdSlice := reflect.MakeSlice(reflect.Indirect(intType).Type(), 5, 8)

    fmt.Println("Kind of slice is:", createdSlice.Kind())
    fmt.Println("Length of slice is:", createdSlice.Len())
    fmt.Println("Capacity of slice is:", createdSlice.Cap())
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kind of slice is: slice
Length of slice is: 5
Capacity of slice is: 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.MakeMap()
&lt;/h3&gt;

&lt;p&gt;The  &lt;code&gt;MakeMap&lt;/code&gt; method will create a new Map of a specified type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    var newMap map[string]interface{}
    var mapType reflect.Value = reflect.ValueOf(&amp;amp;newMap)
    mapCreated := reflect.MakeMap(reflect.Indirect(mapType).Type())

    fmt.Println("Kind of map created is", mapCreated.Kind())
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kind of map created is map
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.MakeChan()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;MakeChan&lt;/code&gt; method will create a new channel with a specified type and buffer-size. Since the created channel has a buffer size it is of type &lt;code&gt;buffer channel&lt;/code&gt;. &lt;code&gt;Unbuffered channels&lt;/code&gt; don't have a buffer size specified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

func main() {
    var newChan chan string
    var chanType reflect.Value = reflect.ValueOf(&amp;amp;newChan)
    chanCreated := reflect.MakeChan(reflect.Indirect(chanType).Type(), 100)

    fmt.Println("Kind of channel created is:", chanCreated.Kind())
    fmt.Println("Capacity of channel create is:", chanCreated.Cap())
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The kind of channel created is: chan
The capacity of channel created is: 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  reflect.MakeFunc()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;MakeFunc&lt;/code&gt; method is used to create a new function value.&lt;br&gt;
It gets the new function of the given Type that wraps the function fn.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "reflect"
)

type Addition func(int64, int64) int64

func main() {
    typ := reflect.TypeOf(Addition(nil))

    // verify if function. If not function return an error
    if typ.Kind() != reflect.Func {
        panic("A function is expected")
    }

    add := reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
        a := args[0].Int()
        b := args[1].Int()
        return []reflect.Value{reflect.ValueOf(a + b)}
    })

    fn, ok := add.Interface().(Addition)
    if !ok {
        return
    }
    fmt.Println(fn(10, 5))
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;You have gone through how to use the reflection package in Golang. This is just the surface of its usage as it can be used in many areas of Golang. The advantage of Reflection is that it allows code to be flexible and handles unknown data types by analyzing their memory representation. However, this is not cost-free as it introduces complexity in code and slows down performance. You can learn more on reflection &lt;a href="https://pkg.go.dev/reflect#pkg-overview"&gt;guidance here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>metaprogramming</category>
    </item>
    <item>
      <title>Deploying a Golang RESTful API with Gin, SQLC and PostgreSQL</title>
      <dc:creator>Geoffrey Sagini Mogambi</dc:creator>
      <pubDate>Wed, 15 Nov 2023 08:36:22 +0000</pubDate>
      <link>https://dev.to/geoff89/deploying-a-golang-restful-api-with-gin-sqlc-and-postgresql-1lbl</link>
      <guid>https://dev.to/geoff89/deploying-a-golang-restful-api-with-gin-sqlc-and-postgresql-1lbl</guid>
      <description>&lt;p&gt;REST which stands for Representative State Transfer is an architectural style for designing APIs(Application Programming Interface). An API is a set of rules through which programs communicate with each other. The API is normally created on the server side and allows the client to talk to it. &lt;/p&gt;

&lt;p&gt;REST has a set of rules on how APIs should be designed and most of these rules follow the CRUD(Create, Read, Update, and Delete) pattern where you request a resource and data is sent back which is called a Response. The request anatomy comprises four sections namely the endpoint which is the request URL, the method, the headers, and the data/body.&lt;/p&gt;

&lt;p&gt;In this article, you will implement a CRUD RESTful API in Golang with Gin HTTP web framework, SQLC for creating CRUD database functions and PostgreSQL as the database engine of choice for this project. You will also learn to use the Golang migrate library for database schema migrations. &lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Setting up the Golang project&lt;/li&gt;
&lt;li&gt;Setting up PostgreSQL with Docker Compose&lt;/li&gt;
&lt;li&gt;Performing database migration with Golang migrate&lt;/li&gt;
&lt;li&gt;Using SQLC to generate Go code from SQL queries&lt;/li&gt;
&lt;li&gt;Implementing CRUD in Golang Rest API&lt;/li&gt;
&lt;li&gt;Route Creation for the Contact Handlers&lt;/li&gt;
&lt;li&gt;Testing the Golang RESTful API with REST Client&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Before getting started ensure you have &lt;a href="https://go.dev/dl/" rel="noopener noreferrer"&gt;Go installed&lt;/a&gt; installed on your machine. At the time of writing this guide 1.21.3 is the latest stable version of Go. &lt;/li&gt;
&lt;li&gt;You should also have &lt;a href="https://code.visualstudio.com/docs/setup/setup-overview" rel="noopener noreferrer"&gt;Vscode installed&lt;/a&gt; as it is the IDE of choice for this exercise but feel free to use any other IDE of your liking. Install &lt;a href="https://code.visualstudio.com/docs/languages/go" rel="noopener noreferrer"&gt;Go extension&lt;/a&gt; for vscode to make it easy to get features like intellisense, code navigation, testing, debugging and many more features that will guide you in your Golang development journey.&lt;/li&gt;
&lt;li&gt;Ensure &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; is also installed on your machine.&lt;/li&gt;
&lt;li&gt;Some basic knowledge of Golang and SQL(Structured Query Language) will also come in handy to follow along this article.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up the Golang project
&lt;/h2&gt;

&lt;p&gt;To start this project navigate to your preferred directory on your machine and  open the terminal. From the terminal create a new folder with the project name, navigate to the project folder, initialize the Golang project and  open VsCode editor. Use the following commands to set up the project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir golang-crudsqlc-rest
cd golang-crudsqlc-rest/
go mod init golang-crudsqlc-rest
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the above setup is done, install the relevant packages for the project by running the following commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
go install github.com/cosmtrek/air@latest
go get github.com/lib/pq
go get github.com/spf13/viper
go get -u github.com/gin-gonic/gin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The migrate package is installed slightly differently from the rest of the packages. Since I am using Ubuntu the below commands will be run at the terminal. If you are using macOS or Windows operating system refer to &lt;a href="https://github.com/golang-migrate/migrate/tree/master/cmd/migrate" rel="noopener noreferrer"&gt;migration installation page&lt;/a&gt; to see how to install migrate CLI.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | apt-key add -
echo "deb https://packagecloud.io/golang-migrate/migrate/ubuntu/ $(lsb_release -sc) main" &amp;gt; /etc/apt/sources.list.d/migrate.list
apt-get update
apt-get install -y migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's have a brief overview of what each package does.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sqlc&lt;/code&gt;: Is a library that is used to generate Golang code 
that has type safe interfaces from SQL queries.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;air&lt;/code&gt;: Is a live reloading utility that is used to observe 
changes in Go applications. Run  the air command in the 
root of your project and it will take care of 
listening to changing events in your code without the need 
to restart the application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pq&lt;/code&gt;: It's GO Postgres driver used for GO database/sql. You 
have to import this driver for you to use the database/sql 
if you are using the Postgresql engine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;viper&lt;/code&gt;: Is a configuration package solution used to read 
configurations of all types ranging from environment 
variables, 
buffer files, command line flags to files written in JSON, 
YAML and TOML to name just but a few.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gin&lt;/code&gt;: Is a web framework written in Go and it comes with a 
lot of prebuilt in features ranging from routes grouping, 
JSON validation, middleware support and error management.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;migrate&lt;/code&gt;: This library helps with database migration 
either through incremental changes in the schema or 
reversal changes made in the database schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up PostgreSQL with Docker Compose
&lt;/h2&gt;

&lt;p&gt;The database of choice used for this project is PostgreSQL. The database engine will be run as a container. To pull the image from docker ensure docker is installed on your machine. Remember this is one of the prerequisites stated earlier on.&lt;br&gt;
At the root of the project create a &lt;code&gt;docker-compose.yaml&lt;/code&gt; file by typing &lt;code&gt;touch docker-compose.yaml&lt;/code&gt;. This file will have the following configurations.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.9"
services:
  postgres:
    image: postgres:latest
    container_name: postgres
    ports:
      - "5432:5432"
    volumes:
      - db:/var/lib/postgresql/data
    env_file:
      - ./app.env

volumes:
  db:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When the above file is run using the required docker-compose command it will pull the latest Postgres image from &lt;a href="https://hub.docker.com/_/postgres" rel="noopener noreferrer"&gt;docker hub&lt;/a&gt; and run it as a Postgres container. The container name is &lt;code&gt;postgres&lt;/code&gt; which will be mapped to port &lt;code&gt;5432&lt;/code&gt; from where the postgres server will listen to. The &lt;code&gt;env_file&lt;/code&gt; property will be mapped to an external file named &lt;code&gt;app.env&lt;/code&gt; which will store sensitive information related to your postgres database. &lt;br&gt;
At the root of your project create an &lt;code&gt;app.env&lt;/code&gt; file with the following credentials. Feel free to use credentials of your choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  app.env
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_DRIVER=postgres
DB_SOURCE=postgresql://root:secret@localhost:5432/contact_db?sslmode=disable
POSTGRES_USER=root
POSTGRES_PASSWORD=secret
POSTGRES_DB=contact_db
SERVER_ADDRESS=8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After setting  the above run the PostgreSQL container with the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The container will be run in a detached mode and will pull the image from docker hub. Once the image has been downloaded and container is up and running you can type &lt;code&gt;docker ps&lt;/code&gt; command to see if postgres name of the container will be displayed at the terminal. The result will be something similar to the one below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffttwekoz0ba8e12dtq0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffttwekoz0ba8e12dtq0j.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To stop the container type the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Performing database migration with Golang migrate
&lt;/h2&gt;

&lt;p&gt;Database migration is one of the most important tasks when it comes to version tracking of data. It involves tracking increments and decrements of version changes in the populated database and this helps to ensure that there are no dirty schema migrations.&lt;br&gt;
In this section you will go through how to write database migration using &lt;a href="https://github.com/golang-migrate/migrate/tree/master/cmd/migrate" rel="noopener noreferrer"&gt;golang-migrate library&lt;/a&gt;. Remember you have already installed golang migrate library in the project setup. If not sure you can always refer the project setup section. To confirm that migrate library is installed type &lt;code&gt;migrate&lt;/code&gt; at the terminal and an output similar to the following will be displayed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgytjjczbccmg8oq0tlw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgytjjczbccmg8oq0tlw4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's describe the commonly used commands for the above output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;create&lt;/code&gt; - Is used to create new migration files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;up&lt;/code&gt; - For migrating files of the schema to a newer 
version based on the prefix sequence.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;down&lt;/code&gt; - Used to migrate files of the schema in a reverse 
manner based on the prefix sequence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With migration package in place You can now create a folder &lt;code&gt;db/migration&lt;/code&gt; where the migration files will reside. Run the following command to create the folder.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p db/migration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can now create the up/down migration files where your SQL code will be placed with the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;migrate create -ext sql -dir db/migration -seq init_schema
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;-ext&lt;/code&gt; flag refers to the extension of the file which 
is SQL and the  &lt;code&gt;-dir&lt;/code&gt; flag refers to the directory where 
SQL files will reside.&lt;/li&gt;
&lt;li&gt;The -seq flag will generate a sequential version number for 
the migration files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you &lt;code&gt;cd&lt;/code&gt; to the &lt;code&gt;db/migration&lt;/code&gt; folder you will notice two migration files have been generated and both have version 1 in the file names prefix. The suffix of the files however is different with one showing &lt;code&gt;up.sql&lt;/code&gt; and another showing &lt;code&gt;down.sql&lt;/code&gt;.&lt;br&gt;
Before any database migration operation is done you need to have a &lt;code&gt;SQL&lt;/code&gt; table in the up migration file and a  reverse operation for removing this table in the down migration file. Add the following SQL code in the folder with the file name &lt;code&gt;db/migration/000001_init_schema.up.sql&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE "contacts"(
    "contact_id" UUID NOT NULL DEFAULT (uuid_generate_v4()),
    "first_name" VARCHAR NOT NULL,
    "last_name" VARCHAR NOT NULL,
    "phone_number" VARCHAR NOT NULL,
    "street" VARCHAR NOT NULL,
    "created_at" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP NOT NULL,
    CONSTRAINT "contacts_pkey" PRIMARY KEY("contact_id")
);

-- CREATE UNIQUE INDEX ON "contacts" ("phone_number");
CREATE UNIQUE INDEX "contacts_phone_number_key" ON "contacts"("phone_number");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The SQL code above does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a table with the name &lt;code&gt;contacts&lt;/code&gt; and the primary 
key column is &lt;code&gt;contact_id&lt;/code&gt;. The primary key column uses 
&lt;code&gt;uuid&lt;/code&gt; data type which helps in ensuring singularity of 
values with no duplicates.&lt;/li&gt;
&lt;li&gt;A unique constraint on the&lt;code&gt;phone_number&lt;/code&gt; column is also 
created which ensures the values of this column will be 
unique when keyed in the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PostgreSQL enables you to store and compare &lt;code&gt;UUID&lt;/code&gt; values but it doesn't have default functions for creating &lt;code&gt;UUID&lt;/code&gt; values by default. It depends on third-party modules that offer algorithms to generate  &lt;code&gt;UUIDS&lt;/code&gt;. You will install &lt;code&gt;uuid-ossp&lt;/code&gt; module which has some functions that contain algorithms to generate &lt;code&gt;UUIDS&lt;/code&gt;.&lt;br&gt;
Before going further let's do one operation in the migration down file. In the &lt;code&gt;db/migration/000001_init_schema.down.sql&lt;/code&gt; file add the following code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DROP TABLE IF EXISTS contacts;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above SQL statement will drop the &lt;code&gt;contacts&lt;/code&gt; table . &lt;br&gt;
Now you are ready to install Postgres &lt;code&gt;uuid-ossp&lt;/code&gt; third-party module. Run the Postgres container with the following command at the terminal.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it postgres bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Proceed to log in as a user and populate the database name you earlier set on the environment variables. Command similar to this one is used &lt;code&gt;psql -U &amp;lt;user&amp;gt; &amp;lt;database name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql -U root contact_db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can now view all the available extensions in Postgres by running the following SQL command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select * from pg_available_extensions;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;An output similar to the following will be displayed.  Scroll down repeatedly in the list until you reach the &lt;code&gt;uuid-ossp&lt;/code&gt; extension as highlighted below in white.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojuw2v40ilroube5mvpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojuw2v40ilroube5mvpw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having located the &lt;code&gt;uuid-ossp&lt;/code&gt; extension on the list, you can now install the extension as shown below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE EXTENSION IF NOT EXISTS  "uuid-ossp";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With Postgres &lt;code&gt;uuid-ossp&lt;/code&gt; extension installed you can  exit the Postgres shell and Docker shell using the &lt;code&gt;exit&lt;/code&gt; command.&lt;br&gt;
It's time to run the migration script and push this table to the database. &lt;br&gt;
Run the following command to execute the migration up script&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;migrate -path db/migration -database  "postgresql://root:secret@localhost:5432/contact_db?sslmode=disable" -verbose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If the migration is successful, proceed to open any Postgres graphical user interface(GUI) client and login with the database credentials specified in &lt;code&gt;app.env&lt;/code&gt; file. The GUI client used in this article is &lt;a href="https://tableplus.com/" rel="noopener noreferrer"&gt;TablePlus&lt;/a&gt; but there are other GUI clients you can still use to connect to the database like &lt;a href="https://www.pgadmin.org/download/" rel="noopener noreferrer"&gt;PgAdmin&lt;/a&gt; and &lt;a href="https://www.beekeeperstudio.io/" rel="noopener noreferrer"&gt;Beekeper Studio&lt;/a&gt;. Connect to the Postgres server container by typing the credentials similar to the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8jq14ddm5m6mxqnt2g6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8jq14ddm5m6mxqnt2g6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the connection is successful the contacts table created by   &lt;a href="https://github.com/golang-migrate/migrate/tree/master/cmd/migrate" rel="noopener noreferrer"&gt;Golang migrate&lt;/a&gt; will be created with a schema definition similar to the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl84j2y23um3izxd2wkcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl84j2y23um3izxd2wkcd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The schema migrations table stores the latest migration version which in this scenario is version 1 since there is a single migration that has been migrated. To revert back to the changes made by the up migration script run the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;migrate -path db/migration -database "postgresql://root:secret@localhost:5432/contact_db?sslmode=disable" -verbose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Using SQLC to generate Go code from SQL queries
&lt;/h2&gt;

&lt;p&gt;Having successfully migrated scripts to the database schema you can go ahead to generate Golang CRUD code with &lt;code&gt;sqlc&lt;/code&gt;. Ensure you have &lt;code&gt;sqlc&lt;/code&gt; installed. Refer to the project setup section to see how to install &lt;code&gt;sqlc&lt;/code&gt;. &lt;br&gt;
Run &lt;code&gt;sqlc&lt;/code&gt; at the terminal and if the output is similar to the following you have successfully installed &lt;code&gt;sqlc&lt;/code&gt; in your machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjt2633jxb7gk4vps4bqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjt2633jxb7gk4vps4bqa.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With sqlc in place run the following command to generate &lt;code&gt;sqlc.yaml&lt;/code&gt; at the root of your project.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sqlc init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A sqlc.yaml file will be generated at the root of the project. Replace the generated content with the following.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sqlc.yaml&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "1"
packages:
  - name: "db"
    path: "./db/sqlc"
    queries: "./db/query/"
    schema: "./db/migration/"
    engine: "postgresql"
    emit_json_tags: true
    emit_prepared_queries: true
    emit_interface: false
    emit_exact_table_names: false
    emit_empty_slices: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;name&lt;/code&gt; option is the name of the Go package generated. 
In this case &lt;code&gt;db&lt;/code&gt; is the package name.&lt;/li&gt;
&lt;li&gt;Next, you specify the folder path where the generated 
Golang files will be generated. Create a new folder &lt;code&gt;sqlc&lt;/code&gt; 
inside the &lt;code&gt;db&lt;/code&gt; so that the &lt;code&gt;path&lt;/code&gt; references the path with 
string &lt;code&gt;./db/sqlc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;queries&lt;/code&gt; tells  sqlc where to look for &lt;code&gt;SQL&lt;/code&gt; query files. 
Create a new folder  &lt;code&gt;query&lt;/code&gt; inside the &lt;code&gt;db&lt;/code&gt; folder so 
that &lt;code&gt;queries&lt;/code&gt; references the path with string &lt;code&gt;./db/query&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;schema&lt;/code&gt; points to where our migration files are 
stored. In your case, it's &lt;code&gt;./db/migration&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;engine&lt;/code&gt; section tells sqlc which database engine to use. 
In this scenario, the database engine is &lt;code&gt;PostgreSQL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;emit_json_tags&lt;/code&gt; if set to true directs sqlc to add &lt;code&gt;JSON 
tags&lt;/code&gt; on the generated structs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;emit_prepared_queries&lt;/code&gt; tells sqlc to generate code that 
supports prepared queries. This is useful in the 
performance optimization of code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;emit_interface&lt;/code&gt; if set to true, outputs a Querier 
interface in the generated package. The querier interface 
generated is useful if you want to mock the db higher- 
level functions.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;emit_exact_table_names&lt;/code&gt; instructs sqlc to create struct 
names that will be the same as table names. The generated 
name of the struct will mirror the table name in 
singularity i.e. contact table will have a Contact 
struct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before generating queries with &lt;code&gt;sqlc generate&lt;/code&gt;  populate the SQL queries in folder &lt;code&gt;db/query/contact.sql&lt;/code&gt; with the following code.&lt;/p&gt;

&lt;h5&gt;
  
  
  db/query/contact.sql
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- name: CreateContact :one
INSERT INTO contacts(
    first_name,
    last_name,
    phone_number,
    street,
    created_at,
    updated_at
) VALUES (
    $1, $2, $3, $4, $5, $6
) RETURNING *;

-- name: GetContactById :one
SELECT * FROM contacts
WHERE contact_id = $1 LIMIT 1;

-- name: ListContacts :many
SELECT * FROM contacts
ORDER BY contact_id
LIMIT $1
OFFSET $2;

-- name: UpdateContact :one
UPDATE contacts
SET
first_name = coalesce(sqlc.narg('first_name'), first_name),
last_name = coalesce(sqlc.narg('last_name'), last_name),
phone_number = coalesce(sqlc.narg('phone_number'), phone_number),
street = coalesce(sqlc.narg('street'), street),
updated_at = coalesce(sqlc.narg('updated_at'), updated_at)
WHERE contact_id = sqlc.arg('contact_id')
RETURNING *;

-- name: DeleteContact :exec
DELETE FROM contacts
WHERE contact_id = $1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Below is a breakdown of what the above code does. Five &lt;code&gt;SQL&lt;/code&gt; queries that represent &lt;code&gt;CRUD&lt;/code&gt; operations have been created for create, insert, update, get and delete operations.&lt;br&gt;
Each query has some annotations namely &lt;code&gt;--name&lt;/code&gt;, &lt;code&gt;:one&lt;/code&gt;, &lt;code&gt;:many&lt;/code&gt; and &lt;code&gt;:exec&lt;/code&gt;. The &lt;code&gt;--name&lt;/code&gt; annotation will generate the function name to be used by the Golang function. For instance &lt;code&gt;-- name: CreateContact :one&lt;/code&gt; annotation tells sqlc to generate Golang function that will have one record.&lt;br&gt;
&lt;code&gt;:many&lt;/code&gt; annotation instructs sqlc generated query to generate multiple row records during the database-specific &lt;code&gt;CRUD&lt;/code&gt; operation. The &lt;code&gt;:exec&lt;/code&gt; annotation label instructs postgres not to return the deleted record.&lt;br&gt;
For nullable parameters &lt;code&gt;sqlc.narg()&lt;/code&gt; is used. It tells sqlc to ignore the nullability it has inferred and replace it with a generated nullable parameter instead. Simply put you can update each field independently without affecting the nullability of fields.&lt;br&gt;
With the SQL queries above explained you can now generate Golang code with &lt;code&gt;sqlc generate&lt;/code&gt;. Once the Golang crud has been generated by sqlc generate, open the &lt;code&gt;db/sqlc&lt;/code&gt; folder and three new Golang files will be generated.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;contact.sql.go&lt;/code&gt; - contains Golang crud functions and struct definitions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;db.tx&lt;/code&gt; - contains the DBTX interface with the four common methods of ExecContext, PrepareContext, QueryContext and QueryRowContext that  SQL db and SQL tx object both have.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;models.go&lt;/code&gt; contains the struct definition for the Contact table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you see red line in visual studio code just run &lt;code&gt;go mod tidy&lt;/code&gt; so that dependencies added by &lt;code&gt;SQLC&lt;/code&gt; are installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Loading Environment Variables with Viper
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/spf13/viper" rel="noopener noreferrer"&gt;Viper&lt;/a&gt; is a Golang package for configuration management of various file formats. Viper finds, loads, and unmarshal configuration files in JSON, TOML, YAML, HCL, INI, envfile or Java properties formats. In this project, viper is used to find values stored in the environment file &lt;code&gt;app.env&lt;/code&gt; which stores sensitive information like database passwords and other secret information relevant to the project.&lt;br&gt;
Ensure you have viper installed and this was done earlier in the project setup section.  Create &lt;code&gt;util/config.go&lt;/code&gt; file in the root of the project with the following code.&lt;/p&gt;

&lt;h5&gt;
  
  
  util/config.go
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package util

import "github.com/spf13/viper"

type Config struct {
    DbDriver         string `mapstructure:"DB_DRIVER"`
    DbSource         string `mapstructure:"DB_SOURCE"`
    PostgresUser     string `mapstructure:"POSTGRES_USER"`
    PostgresPassword string `mapstructure:"POSTGRES_PASSWORD"`
    PostgresDb       string `mapstructure:"POSTGRES_DB"`
    ServerAddress    string `mapstructure:"SERVER_ADDRESS"`
}

func LoadConfig(path string) (config Config, err error) {
    viper.AddConfigPath(path)
    viper.SetConfigName("app")
    viper.SetConfigType("env")

    viper.AutomaticEnv()

    err = viper.ReadInConfig()
    if err != nil {
        return
    }

    err = viper.Unmarshal(&amp;amp;config)
    return
}

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

&lt;/div&gt;

&lt;p&gt;With this in place &lt;code&gt;Viper&lt;/code&gt; will now load the environment variables from the &lt;code&gt;util/config.go&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Request Validation Structs
&lt;/h3&gt;

&lt;p&gt;SQLC has already generated structs from  &lt;code&gt;SQl&lt;/code&gt; queries which can be passed to  Gin web framework for validation of the request body during request of the respective resource endpoints. However since more validation bindings will be required, you can go ahead and create your custom structs.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;schemas/contacts.schema.go&lt;/code&gt; file and add the following Golang structs.&lt;/p&gt;

&lt;h5&gt;
  
  
  schemas/contacts.schema.go
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package schemas

type CreateContact struct {
    FirstName   string `json:"first_name" binding:"required"`
    LastName    string `json:"last_name" binding:"required"`
    PhoneNumber string `json:"phone_number" binding:"required"`
    Street      string `json:"street" binding:"required"`
}

type UpdateContact struct {
    FirstName   string `json:"first_name"`
    LastName    string `json:"last_name"`
    PhoneNumber string `json:"phone_number"`
    Street      string `json:"street"`
}

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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CreateContact&lt;/code&gt; struct will be validated by Gin Gonic when 
creating contacts request payload records in the database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UpdateContact&lt;/code&gt; struct will be validated by Gin Gonic when updating the contacts payload records in the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Route Controller Creation
&lt;/h3&gt;

&lt;p&gt;In this section, you will perform the CRUD operations by creating five functions. These functions will perform the CRUD operations by using the generated &lt;code&gt;sqlc&lt;/code&gt; CRUD methods that were generated from the SQL queries.&lt;/p&gt;

&lt;p&gt;The five functions to be used are defined below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CreateContact&lt;/code&gt; - Adds new contact records to the 
database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UpdateContact&lt;/code&gt; - Will edit the contact records 
already stored in the database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetContactById&lt;/code&gt; - Retrieve a single record in the 
database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetAllContacts&lt;/code&gt; - Returns all the selected contacts 
from the database.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;DeleteContactById&lt;/code&gt; - Removes an instance of a record 
from the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ensure you have &lt;code&gt;Gin Gonic Http&lt;/code&gt; library installed and this has already been covered in the project setup section.&lt;br&gt;
Create &lt;code&gt;controllers/contact.controllers.go&lt;/code&gt; file where all your &lt;code&gt;CRUD&lt;/code&gt; methods will be stored and add the following code to begin with.&lt;/p&gt;

&lt;h5&gt;
  
  
  controllers/contact.controllers.go
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package controllers

import (
    "context"
    "database/sql"
    "net/http"
    "strconv"
    "time"

    db "github.com/Geoff89/sqlccrud/db/sqlc"
    "github.com/Geoff89/sqlccrud/schemas"

    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
)

type ContactController struct {
    db  *db.Queries
    ctx context.Context
}

func NewContactController(db *db.Queries, ctx context.Context) *ContactController {
    return &amp;amp;ContactController{db, ctx}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Implementing CRUD in Golang Rest API
&lt;/h3&gt;
&lt;h5&gt;
  
  
  Creating a post route handler for contact creation.
&lt;/h5&gt;

&lt;p&gt;This route handler will be called when a &lt;code&gt;POST&lt;/code&gt; request is made to the endpoint &lt;code&gt;http://localhost:8000/api/contacts&lt;/code&gt;.   In the file &lt;code&gt;controllers/contact.controller.go&lt;/code&gt; add the following code.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Create contact  handler
func (cc *ContactController) CreateContact(ctx *gin.Context) {
    var payload *schemas.CreateContact

    if err := ctx.ShouldBindJSON(&amp;amp;payload); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{"status": "Failed payload", "error": err.Error()})
        return
    }

    now := time.Now()
    args := &amp;amp;db.CreateContactParams{
        FirstName:   payload.FirstName,
        LastName:    payload.LastName,
        PhoneNumber: payload.PhoneNumber,
        Street:      payload.Street,
        CreatedAt:   now,
        UpdatedAt:   now,
    }

    contact, err := cc.db.CreateContact(ctx, *args)

    if err != nil {
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "successfully created contact", "contact": contact})
}

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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;schemas.CreateContact&lt;/code&gt; struct is bound to  &lt;code&gt;ctx.ShouldBindJSON()&lt;/code&gt; method to validate the request body against the json tags validation rules listed in the struct. Afterwards, initialize the &lt;code&gt;&amp;amp;db.CreateContactParams{}&lt;/code&gt; struct with the required fields provided in the request payload. &lt;code&gt;db.CreateContact()&lt;/code&gt; CRUD method is called afterward to insert a new record in the database and if successful &lt;code&gt;http.StatusOK&lt;/code&gt; will be shown.&lt;/p&gt;

&lt;h5&gt;
  
  
  Adding an update route handler for updating contacts.
&lt;/h5&gt;

&lt;p&gt;This is the second route endpoint created to edit contact records in the database at endpoint &lt;code&gt;http://localhost:8000/api/contacts/:contactId&lt;/code&gt; when &lt;code&gt;PATCH&lt;/code&gt; request is used.&lt;/p&gt;

&lt;h5&gt;
  
  
  controllers/contact.controller.go
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Update contact handler
func (cc *ContactController) UpdateContact(ctx *gin.Context) {
    var payload *schemas.UpdateContact
    contactId := ctx.Param("contactId")

    if err := ctx.ShouldBindJSON(&amp;amp;payload); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{"status": "Failed payload", "error": err.Error()})
        return
    }

    now := time.Now()
    args := &amp;amp;db.UpdateContactParams{
        ContactID:   uuid.MustParse(contactId),
        FirstName:   sql.NullString{String: payload.FirstName, Valid: payload.FirstName != ""},
        LastName:    sql.NullString{String: payload.LastName, Valid: payload.LastName != ""},
        PhoneNumber: sql.NullString{String: payload.PhoneNumber, Valid: payload.PhoneNumber != ""},
        Street:      sql.NullString{String: payload.PhoneNumber, Valid: payload.Street != ""},
        UpdatedAt:   sql.NullTime{Time: now, Valid: true},
    }

    contact, err := cc.db.UpdateContact(ctx, *args)

    if err != nil {
        if err == sql.ErrNoRows {
            ctx.JSON(http.StatusNotFound, gin.H{"status": "failed", "message": "Failed to retrieve contact with this ID"})
            return
        }
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "successfully updated contact", "contact": contact})
}

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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;schemas.UpdateContact&lt;/code&gt; struct is bound to  &lt;code&gt;ctx.ShouldBindJSON()&lt;/code&gt; method to validate the request body against validation rules listed in the struct.  Next, the ID of the record to be updated is retrieved from the request parameter and &lt;code&gt;db.UpdateContactParams{}&lt;/code&gt; struct initialized with the required updated fields. &lt;code&gt;db.UpdateContact()&lt;/code&gt; CRUD method is called afterwards to update the specified record in the database. &lt;/p&gt;

&lt;h5&gt;
  
  
  Retrieving a single contact record handler
&lt;/h5&gt;

&lt;p&gt;This endpoint &lt;code&gt;http://localhost:8000/api/contacts/:contactId&lt;/code&gt; will get a specific contact record when &lt;code&gt;GET&lt;/code&gt; request is called . The specified ID parameter will get the specific record in the database and call &lt;code&gt;db.GetContactById()&lt;/code&gt; method wich will retrieve the record that matches the parameter ID.&lt;/p&gt;

&lt;h5&gt;
  
  
  controllers/contact.controller.go
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Get a single handler
func (cc *ContactController) GetContactById(ctx *gin.Context) {
    contactId := ctx.Param("contactId")

    contact, err := cc.db.GetContactById(ctx, uuid.MustParse(contactId))
    if err != nil {
        if err == sql.ErrNoRows {
            ctx.JSON(http.StatusNotFound, gin.H{"status": "failed", "message": "Failed to retrieve contact with this ID"})
            return
        }
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "Successfully retrived id", "contact": contact})
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h5&gt;
  
  
  Getting all records handler
&lt;/h5&gt;

&lt;p&gt;This handler will retrieve a specific number of records from the database when a request is made from endpoint &lt;code&gt;http://localhost:8000/api/contacts?page=1&amp;amp;limit=10&lt;/code&gt;. &lt;/p&gt;
&lt;h5&gt;
  
  
  controllers/contact.controllers.go
&lt;/h5&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Retrieve all records handlers
func (cc *ContactController) GetAllContacts(ctx *gin.Context) {
    var page = ctx.DefaultQuery("page", "1")
    var limit = ctx.DefaultQuery("limit", "10")

    reqPageID, _ := strconv.Atoi(page)
    reqLimit, _ := strconv.Atoi(limit)
    offset := (reqPageID - 1) * reqLimit

    args := &amp;amp;db.ListContactsParams{
        Limit:  int32(reqLimit),
        Offset: int32(offset),
    }

    contacts, err := cc.db.ListContacts(ctx, *args)
    if err != nil {
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed to retrieve contacts", "error": err.Error()})
        return
    }

    if contacts == nil {
        contacts = []db.Contact{}
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "Successfully retrieved all contacts", "size": len(contacts), "contacts": contacts})
}

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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;.DefaultQuery()&lt;/code&gt; is used to specify query parameters &lt;code&gt;page&lt;/code&gt; and &lt;code&gt;limit&lt;/code&gt;. These query parameters are useful for pagination. The &lt;code&gt;limit&lt;/code&gt; query sets the number of rows to be retrieved from the database and the &lt;code&gt;page&lt;/code&gt; query parameter is useful for pagination of your records. Next, the &lt;code&gt;&amp;amp;db.ListContactsParams{}&lt;/code&gt; is initialized with the specific query parameters before calling &lt;code&gt;db.ListContacts()&lt;/code&gt; method to get all records from the database.&lt;/p&gt;

&lt;h5&gt;
  
  
  Deleting record route handler
&lt;/h5&gt;

&lt;p&gt;This endpoint will delete a specific record from the database as specified by the &lt;code&gt;contactID&lt;/code&gt; parameter when &lt;br&gt;
&lt;code&gt;http://localhost:8000/api/contacts/:contactId&lt;/code&gt; endpoint  &lt;code&gt;DELETE&lt;/code&gt; request is made. The &lt;code&gt;db.GetContactById()&lt;/code&gt; is used to confirm whether the specific record to be deleted exists in the database after which &lt;code&gt;db.DeleteContact()&lt;/code&gt; deletes the specific record from the database.&lt;/p&gt;

&lt;h5&gt;
  
  
  controllers/contact.controllers.go
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Deleting contact handlers
func (cc *ContactController) DeleteContactById(ctx *gin.Context) {
    contactId := ctx.Param("contactId")

    _, err := cc.db.GetContactById(ctx, uuid.MustParse(contactId))
    if err != nil {
        if err == sql.ErrNoRows {
            ctx.JSON(http.StatusNotFound, gin.H{"status": "failed", "message": "Failed to retrieve contact with this ID"})
            return
        }
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    err = cc.db.DeleteContact(ctx, uuid.MustParse(contactId))
    if err != nil {
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "failed", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusNoContent, gin.H{"status": "successfuly deleted"})

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The complete source code for the route handlers will be as follows:&lt;/p&gt;

&lt;h5&gt;
  
  
  controllers/contact.controllers.go
&lt;/h5&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package controllers

import (
    "context"
    "database/sql"
    "net/http"
    "strconv"
    "time"

    db "github.com/Geoff89/sqlccrud/db/sqlc"
    "github.com/Geoff89/sqlccrud/schemas"

    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
)

type ContactController struct {
    db  *db.Queries
    ctx context.Context
}

func NewContactController(db *db.Queries, ctx context.Context) *ContactController {
    return &amp;amp;ContactController{db, ctx}
}

// Create contact  handler
func (cc *ContactController) CreateContact(ctx *gin.Context) {
    var payload *schemas.CreateContact

    if err := ctx.ShouldBindJSON(&amp;amp;payload); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{"status": "Failed payload", "error": err.Error()})
        return
    }

    now := time.Now()
    args := &amp;amp;db.CreateContactParams{
        FirstName:   payload.FirstName,
        LastName:    payload.LastName,
        PhoneNumber: payload.PhoneNumber,
        Street:      payload.Street,
        CreatedAt:   now,
        UpdatedAt:   now,
    }

    contact, err := cc.db.CreateContact(ctx, *args)

    if err != nil {
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "successfully created contact", "contact": contact})
}

// Update contact handler
func (cc *ContactController) UpdateContact(ctx *gin.Context) {
    var payload *schemas.UpdateContact
    contactId := ctx.Param("contactId")

    if err := ctx.ShouldBindJSON(&amp;amp;payload); err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{"status": "Failed payload", "error": err.Error()})
        return
    }

    now := time.Now()
    args := &amp;amp;db.UpdateContactParams{
        ContactID:   uuid.MustParse(contactId),
        FirstName:   sql.NullString{String: payload.FirstName, Valid: payload.FirstName != ""},
        LastName:    sql.NullString{String: payload.LastName, Valid: payload.LastName != ""},
        PhoneNumber: sql.NullString{String: payload.PhoneNumber, Valid: payload.PhoneNumber != ""},
        Street:      sql.NullString{String: payload.PhoneNumber, Valid: payload.Street != ""},
        UpdatedAt:   sql.NullTime{Time: now, Valid: true},
    }

    contact, err := cc.db.UpdateContact(ctx, *args)

    if err != nil {
        if err == sql.ErrNoRows {
            ctx.JSON(http.StatusNotFound, gin.H{"status": "failed", "message": "Failed to retrieve contact with this ID"})
            return
        }
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "successfully updated contact", "contact": contact})
}

// Get a single handler
func (cc *ContactController) GetContactById(ctx *gin.Context) {
    contactId := ctx.Param("contactId")

    contact, err := cc.db.GetContactById(ctx, uuid.MustParse(contactId))
    if err != nil {
        if err == sql.ErrNoRows {
            ctx.JSON(http.StatusNotFound, gin.H{"status": "failed", "message": "Failed to retrieve contact with this ID"})
            return
        }
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "Successfully retrived id", "contact": contact})
}

// Retrieve all records handlers
func (cc *ContactController) GetAllContacts(ctx *gin.Context) {
    var page = ctx.DefaultQuery("page", "1")
    var limit = ctx.DefaultQuery("limit", "10")

    reqPageID, _ := strconv.Atoi(page)
    reqLimit, _ := strconv.Atoi(limit)
    offset := (reqPageID - 1) * reqLimit

    args := &amp;amp;db.ListContactsParams{
        Limit:  int32(reqLimit),
        Offset: int32(offset),
    }

    contacts, err := cc.db.ListContacts(ctx, *args)
    if err != nil {
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed to retrieve contacts", "error": err.Error()})
        return
    }

    if contacts == nil {
        contacts = []db.Contact{}
    }

    ctx.JSON(http.StatusOK, gin.H{"status": "Successfully retrieved all contacts", "size": len(contacts), "contacts": contacts})
}

// Deleting contact handlers
func (cc *ContactController) DeleteContactById(ctx *gin.Context) {
    contactId := ctx.Param("contactId")

    _, err := cc.db.GetContactById(ctx, uuid.MustParse(contactId))
    if err != nil {
        if err == sql.ErrNoRows {
            ctx.JSON(http.StatusNotFound, gin.H{"status": "failed", "message": "Failed to retrieve contact with this ID"})
            return
        }
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "Failed retrieving contact", "error": err.Error()})
        return
    }

    err = cc.db.DeleteContact(ctx, uuid.MustParse(contactId))
    if err != nil {
        ctx.JSON(http.StatusBadGateway, gin.H{"status": "failed", "error": err.Error()})
        return
    }

    ctx.JSON(http.StatusNoContent, gin.H{"status": "successfuly deleted"})

}

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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Route Creation for the Contact Handlers
&lt;/h3&gt;

&lt;p&gt;With the specific route controllers in place, it's time to create Gin Gonic router where CRUD endpoints for the controller handlers will be invoked.&lt;br&gt;
Create a &lt;code&gt;route/contact.route.go&lt;/code&gt; file with the following code&lt;/p&gt;
&lt;h5&gt;
  
  
  routes/contact.route.go
&lt;/h5&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package routes

import (
    "github.com/Geoff89/sqlccrud/controllers"
    "github.com/gin-gonic/gin"
)

type ContactRoutes struct {
    contactController controllers.ContactController
}

func NewRouteContact(contactController controllers.ContactController) ContactRoutes {
    return ContactRoutes{contactController}
}

func (cr *ContactRoutes) ContactRoute(rg *gin.RouterGroup) {

    router := rg.Group("contacts")
    router.POST("/", cr.contactController.CreateContact)
    router.GET("/", cr.contactController.GetAllContacts)
    router.PATCH("/:contactId", cr.contactController.UpdateContact)
    router.GET("/:contactId", cr.contactController.GetContactById)
    router.DELETE("/:contactId", cr.contactController.DeleteContactById)
}

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

&lt;/div&gt;

&lt;p&gt;The final step to do before testing your endpoints is to create the &lt;code&gt;main.go&lt;/code&gt; file which is the main entry point to your API project when the GIN server is started and connection to the database is made. Add the following code to the main.go file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "context"
    "database/sql"
    "fmt"
    "log"
    "net/http"

    "github.com/Geoff89/sqlccrud/controllers"
    dbCon "github.com/Geoff89/sqlccrud/db/sqlc"
    "github.com/Geoff89/sqlccrud/routes"
    "github.com/Geoff89/sqlccrud/util"
    "github.com/gin-gonic/gin"
    _ "github.com/lib/pq"
)

var (
    server *gin.Engine
    db     *dbCon.Queries
    ctx    context.Context

    ContactController controllers.ContactController
    ContactRoutes     routes.ContactRoutes
)

func init() {
    ctx = context.TODO()
    config, err := util.LoadConfig(".")

    if err != nil {
        log.Fatalf("could not loadconfig: %v", err)
    }

    conn, err := sql.Open(config.DbDriver, config.DbSource)
    if err != nil {
        log.Fatalf("Could not connect to database: %v", err)
    }

    db = dbCon.New(conn)

    fmt.Println("PostgreSql connected successfully...")

    ContactController = *controllers.NewContactController(db, ctx)
    ContactRoutes = routes.NewRouteContact(ContactController)

    server = gin.Default()
}

func main() {
    config, err := util.LoadConfig(".")

    if err != nil {
        log.Fatalf("failed to load config: %v", err)
    }

    router := server.Group("/api")

    router.GET("/healthcheck", func(ctx *gin.Context) {
        ctx.JSON(http.StatusOK, gin.H{"message": "The contact APi is working fine"})
    })

    ContactRoutes.ContactRoute(router)

    server.NoRoute(func(ctx *gin.Context) {
        ctx.JSON(http.StatusNotFound, gin.H{"status": "failed", "message": fmt.Sprintf("The specified route %s not found", ctx.Request.URL)})
    })

    log.Fatal(server.Run(":" + config.ServerAddress))
}

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

&lt;/div&gt;

&lt;p&gt;Going through the above code an &lt;code&gt;init&lt;/code&gt; function loads the environment variables from the app.env file, connects to the database and starts an instance of Gin Gonic engine. In Golang the init function is usually executed first before the &lt;code&gt;main&lt;/code&gt; function. For tasks that you want to run before firing the server such as database connections use &lt;code&gt;init&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Finally, in the main function, you create the API routes and start the GIN server to listen to the port provided. &lt;br&gt;
Now it is time to test the RESTful api endpoints. Type &lt;code&gt;air&lt;/code&gt; at the terminal in the root of the project. It will automatically start the server for you, and show the endpoints you will make requests to. When run successfully at the terminal air will display output similar to the one below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4lo73c27zlywghczmss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4lo73c27zlywghczmss.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Golang RESTful API with REST Client
&lt;/h2&gt;

&lt;p&gt;The Golang API server is now running together with SQLC for running database operations. Here you will use &lt;a href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client" rel="noopener noreferrer"&gt;REST Client extension for Visual Studio&lt;/a&gt; to run the API tests. For advanced testing of APIs with more features you can use &lt;a href="https://www.postman.com/downloads/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP POST Request: This will create records.
&lt;/h4&gt;

&lt;p&gt;This request will create a new record in the database. A HTTP POST request will be made to the endpoint &lt;code&gt;http://localhost:8000/api/contacts&lt;/code&gt; with a json object in the request body. Gin Gonic server will then validate the request body with the given &lt;code&gt;Golang&lt;/code&gt; CreateContact struct instructions and finally invoke &lt;code&gt;.CreateContact()&lt;/code&gt; method to insert a new contact record in the database. Add a few more records following the screenshot guide below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdthdlwlgvgrd4g18mzz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdthdlwlgvgrd4g18mzz5.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP GET Request: This will retrieve all records
&lt;/h4&gt;

&lt;p&gt;To retrieve all records in the database make a &lt;code&gt;GET&lt;/code&gt; request to the endpoint &lt;code&gt;http://localhost:8000/api/contacts&lt;/code&gt;. For pagination purposes, this request will retrieve the first 10 results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25i6byrssmrdd3lpaour.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25i6byrssmrdd3lpaour.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP GET Request: Retrieving a single record.
&lt;/h4&gt;

&lt;p&gt;To get a single record from the database,  send a &lt;code&gt;GET&lt;/code&gt; request to the &lt;code&gt;http://localhost:8000/api/contacts/:contactId&lt;/code&gt; endpoint. The server will query the database and retrieve the record that matches the params contactId requested by client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jfwkcrrn4jlcsuakwi6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jfwkcrrn4jlcsuakwi6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP PATCH Request: will update a specified record
&lt;/h4&gt;

&lt;p&gt;For updating a record in the database make a &lt;code&gt;PATCH&lt;/code&gt; HTTP request to the &lt;code&gt;http://localhost:8000/api/contacts/:contactId&lt;/code&gt; endpoint with a specific ID from the database record as the value of the URL parameter. In the body of the JSON object change values of the columns you want to update. Proceed to make a request and Gin Gonic Server will only update the fields requested to be updated and return an updated record to the client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5er8y8e8ki8cwrijhfag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5er8y8e8ki8cwrijhfag.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP DELETE Request:  This will remove a record
&lt;/h4&gt;

&lt;p&gt;To remove a record from the database make a request at the &lt;br&gt;
&lt;code&gt;http://localhost:8000/api/contacts/:contactId&lt;/code&gt; endpoint by specifying the ID from the database as the URL parameter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9u75p2ccgpt8h3st5lbc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9u75p2ccgpt8h3st5lbc.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In this guide, you learned the principles of RESTful APIs. You started by generating Golang CRUD code with SQLC and later on ran database migration using the Golang migrate library. You also built a RESTful CRUD API that runs on Gin Gonic HTTP web framework and uses PostgreSQL as the database of choice.&lt;/p&gt;

&lt;p&gt;You can find the code for this project in this &lt;a href="https://github.com/Geoff89/golang-sqlc-gorm-rest" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>sql</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
