<?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: Berkeli Halmyradov</title>
    <description>The latest articles on DEV Community by Berkeli Halmyradov (@berkeli).</description>
    <link>https://dev.to/berkeli</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1007718%2F1ffb4c76-51be-4a68-bd66-91b55f10667f.jpeg</url>
      <title>DEV Community: Berkeli Halmyradov</title>
      <link>https://dev.to/berkeli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/berkeli"/>
    <language>en</language>
    <item>
      <title>CodingChallenges in GO - initial setup</title>
      <dc:creator>Berkeli Halmyradov</dc:creator>
      <pubDate>Sat, 17 Feb 2024 22:04:32 +0000</pubDate>
      <link>https://dev.to/berkeli/codingchallenges-in-go-initial-setup-kdj</link>
      <guid>https://dev.to/berkeli/codingchallenges-in-go-initial-setup-kdj</guid>
      <description>&lt;p&gt;Hello world! &lt;/p&gt;

&lt;p&gt;Procrastination is real and I've been putting off starting a "blog" for far too long. Why not use this opportunity and go over the fairly new &lt;a href="https://codingchallenges.fyi/"&gt;codingchallenges.fyi&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In this series, I will be using Go and Test-Driven-Development while walking through the challenges and explaining my thoughts process. So without further ado, let's get going. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Tools
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;go&lt;/strong&gt; - I will be coding in golang, so &lt;a href="https://go.dev/doc/install"&gt;https://go.dev/doc/install&lt;/a&gt; is essential. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/spf13/cobra"&gt;cobra-cli&lt;/a&gt;&lt;/strong&gt; I will also be using cobra go package as most of the challenges are cli oriented. Cobra provides a CLI tool that can help you produce boilerplate code to save you some time.&lt;/li&gt;
&lt;li&gt;[OPTIONAL] &lt;strong&gt;&lt;a href="https://github.com/gotestyourself/gotestsum"&gt;gotestsum&lt;/a&gt;&lt;/strong&gt; - this is an excellent go testing tool that has many features over the standard &lt;code&gt;go test&lt;/code&gt; command. I hihgly recommend!&lt;/li&gt;
&lt;li&gt;[OPTIONAL] &lt;strong&gt;Unix environment&lt;/strong&gt; - this is not a requirement, but a nice to have. Most of the tools we will be creating are only available in unix, so having a system that runs unix or WSL for windows will be handy when you need to do a parity check.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2. Repository Setup
&lt;/h2&gt;

&lt;p&gt;To get started, I have created an empty git repository on github and cloned it to my computer.&lt;/p&gt;

&lt;p&gt;Now we need to initialize our go module, I will &lt;code&gt;cd&lt;/code&gt; into the newly cloned directory and 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;go mod init github.com/berkeli/coding-challenges
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have given my module the path to my git repository, as that makes it easy to import &amp;amp; reference things. &lt;/p&gt;

&lt;h2&gt;
  
  
  3. Creating hello world
&lt;/h2&gt;

&lt;p&gt;Now we will initialize our CLI application and write simple &lt;code&gt;Hello World!&lt;/code&gt; to the terminal. &lt;/p&gt;

&lt;p&gt;I will run &lt;code&gt;cobra-cli init .&lt;/code&gt; which creates the basic boilerplate for our application. Once done, you should be able to run the application and it will display the description for our &lt;code&gt;root&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;go run .                                                                                                                                                                                                                                              
A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's update the handler function for the &lt;code&gt;rootCmd&lt;/code&gt; (located in &lt;code&gt;cmd/root.go&lt;/code&gt;) so we have our hello world:&lt;/p&gt;

&lt;p&gt;from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
    fmt.Println("hello world!")
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and voila! we have our hello world:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run .                                                                                                                                                                                                                                                   
hello world!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we won't be attaching a handler to the &lt;code&gt;rootCmd&lt;/code&gt;, so we can undo our change and the cleanup comments and descriptions so it matches what we are trying to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  A few notes on project structure
&lt;/h3&gt;

&lt;p&gt;For this project I will be following the follwowing structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── cmd &amp;lt;-- most of our work will live here
│   ├── go-wc &amp;lt;-- subdirectory for each command/challenge, e.g. wc command
│   │   ├── main.go &amp;lt;-- logic for wc command
│   │   ├── main_test.go &amp;lt;-- tests for wc command
│   │   └── test.txt &amp;lt;-- any additional fixtures needed for testing
│   └── root.go &amp;lt;-- our root command, this will only register child commands
├── go.mod
├── go.sum
└── main.go 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cobra-cli&lt;/code&gt; has a useful command for adding new commands &lt;code&gt;cobra-cli add &amp;lt;new-command&amp;gt;&lt;/code&gt;, but I won't be using that much as it won't be following the folder structure I've chosen. It creates files directly in &lt;code&gt;cmd&lt;/code&gt; folder without subdirectories which could get very busy in this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests &amp;amp; CI
&lt;/h2&gt;

&lt;p&gt;Of course, you can't have TDD without proper CI (continuous integration) setup. So let's get that out of the way and introduce a github action that will test our code. &lt;/p&gt;

&lt;p&gt;We can create a YAML file in &lt;code&gt;.github/workflows/&lt;/code&gt; directory, I named mine &lt;code&gt;go-test.yaml&lt;/code&gt; and place the following inside of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Go Test

on: [push]

jobs:
  example:
    name: run tests
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version-file: ./go.mod
        id: go
      - name: Run Go tests
        run: go run gotest.tools/gotestsum@latest --junitfile unit-tests.xml
      - name: Test Summary
        uses: test-summary/action@v2
        with:
          paths: "unit-tests.xml"
        if: always()

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

&lt;/div&gt;



&lt;p&gt;The action about has 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checkout the repository (get the latest commit)&lt;/li&gt;
&lt;li&gt;Install gotestsum&lt;/li&gt;
&lt;li&gt;Run go tests with gotestsum&lt;/li&gt;
&lt;li&gt;Create a summary from the output of gotestsum&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it for the setup, let's go implement &lt;code&gt;wc&lt;/code&gt; command next!&lt;/p&gt;

&lt;p&gt;The code for this series is available at &lt;a href="https://github.com/berkeli/coding-challenges"&gt;https://github.com/berkeli/coding-challenges&lt;/a&gt; &lt;br&gt;
The code for this post is on this &lt;a href="https://github.com/berkeli/coding-challenges/pull/1"&gt;Pull Request&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;UPDATE&lt;/strong&gt; [18/02/24] - I realized that this series will contain other types of applications that CLI, so I have made a small re-org of the repo to make it a GO monorepo.
&lt;/h2&gt;

&lt;p&gt;The new structure is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── cmd
│   └── cli &amp;lt;-- these will be individual applications
│       └── main.go
├── go.mod
├── go.sum
└── pkg &amp;lt;-- this will contain individual challenges as importable packages
    └── wc &amp;lt;-- wc package, which is the next challenge
        ├── main.go
        ├── main_test.go
        └── test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So from the example above, we will have a cli package which is our &lt;code&gt;gocc&lt;/code&gt; (go coding challenges) app that will register subcommands like wc, ls, etc. &lt;/p&gt;

&lt;p&gt;These changes are recording in &lt;a href="https://github.com/berkeli/coding-challenges/pull/2"&gt;2nd Pull request&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run our cli tool, we will now be running &lt;code&gt;go run ./cmd/cli&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
