DEV Community

Cover image for My first CLI with Go
Tuhin Bar
Tuhin Bar

Posted on

My first CLI with Go

I always felt a bit anxious to write about my experiences. Well, I think I can deal with it now. It was an early morning in August when I decided to write a CLI tool just to "practice" Go as I had learned the basics a few days earlier. I do not watch many tutorials nowadays but I watched Nana's Video on Golang and it was pretty awesome. So, let's jump right in.

The reason

I wanted to experiment with Go to learn the os module. The first thought that came to my mind was to create a turborepo with Golang as a server. Yes, I know that we cannot host it in Vercel, but the idea was to create a fast and secure server with Golang. We can use an API proxy in Vercel to rewrite the requests from the client side. However, you will be required to host your Go server separately in some places like Railway or Render. This doesn't follow the rule of a mono repo architecture, it is just maintaining all the code in a single place and building a strong server. It was named turbo-g (turbo + go).

Well, after creating a template project, I realized that Turbo has some issues with hot reload and many other things. So, eventually, I dropped the idea and moved on to create something else.

When creating this template project, I saw that I had to set up the server manually and I used gofiber as it has express-like functionalities, and as a MERN stack developer, I found it very easy to use. Once I thought to make a server-project generator in Express as well, but they already have one, it is called express-generator. Then I thought there might be the same thing for Fiber as well. But when I searched in GitHub with the topic:go-backend-template, I only found pre-made templates that you can clone and use for your projects. That's when I decided to give it a shot.

The process

Making a CLI with go is fairly simple, as go codes are compiled into a binary executable. But, I didn't know how to create files and folders using the os module. In JavaScript(NodeJs), we can use the fs module to manage files. All thanks to the docs for helping me out. I already knew what a basic backend project looks like in Express and Fiber as well. My approach was very simple. I will create a CLI tool that will use a few flags like --init and --name for the project name and it will generate a project and go.mod with fiber as a dependency.

Then I got stuck in the thing called templates. Templates are a skeleton of a go file. A template holds the content of the file. It was interesting to learn about templates. Then it was easy to take the project name from the flag and create all file folders using os.MkdirAlland parse the templates with the text/template module and get the content to create the files. All the details of these modules can be found in the Golang docs I mentioned above. Then it was done! πŸŽ‰ But..

dirs := []string{"cmd", "internal/handlers", "internal/middleware", "internal/models", "internal/routes", "internal/services", "config"}
    for _, dir := range dirs {
        if err := os.MkdirAll(filepath.Join(projectPath, dir), os.ModePerm); err != nil {
            return fmt.Errorf("❗Failed to create directory %s: %w", dir, err)
        }
    }
Enter fullscreen mode Exit fullscreen mode

The problems

  • I found out soon that I wasn't using github.com/<username>/<repo> as the module name which was a problem I encountered when I was learning about the go modules for the first time. Then I learned about the module path from here. So, what I did to solve the problem is very simple. I just added a -gh flag for users to add their GitHub Username to crate the module assuming the project name is the GitHub repo.

  • Another problem that still exists that is I did not provide any code in the middleware template file and the config template file. Users can use MongoDB or PostgreSQL as a database so it was unnecessary to provide any single or both configs in the template. Well, to fix this I created an issue and anyone reading this blog can contribute to solving this problem. I already figured out a way but this comes down to the third problem.

  • The CLI can take a user input called -db to get the user's choice of databases like MongoDB or PostgreSQL to make a dummy connection in the Config template. But, as the code grows to solve these kinds of problems, the CLI will be unusable. It already has 2 required flags and one optional which are --init, -gh, and -name, and if we add a -db flag it will be a very long command. To solve this problem I am going to modify the CLI as an interactive one like create-next-app. After this change, we can add many options for customization. I am already working on this. So, if you want to contribute, you are welcome. You can find the issue here.

  • The last problem for now is a hot reload module. Whenever we create a fiber app we don't have any change listener by default. If fiber has this already and I do not know about it then forgive me for that I am relatively new to this. If you know anything about this, let me know in the comments. To solve this problem I figured out to include air in the project.

The end

This is the story of Optical . However, the blog intends to let you guys know about the little project and also it is an invitation to contribute to the project if you want.

The journey has just started and it has been very interesting so far. I learned a lot of things and am willing to learn more ahead. This was my first blog here, so if I made any mistake or overlooked something, please ignore that and forgive me. it will be better next time.

Thanks, everyone for reading the blog, give a ⭐ to Optical if you find it interesting. Also, share if you know anyone willing to contribute. Also, if you find any issues or have any ideas for improvement, you can create an issue here

Thanks again.

Top comments (4)

Collapse
 
abdulmuminyqn profile image
Abdulmumin yaqeen

Well documented man, I read this like I was in your shoes πŸ˜….

Not a go developer, but rooting for you πŸ™Œ.

Collapse
 
tuhinbar profile image
Tuhin Bar

Thanks man. It was nice hearing from you. Thanks for the encouragement!

Collapse
 
raven_halder_304826bf4489 profile image
Raven Halder

Damn, your blog doesn't read like AI generated. Seeing someone describe so much, even the minute detail interested me to read further. 🫑

Your experience now made me thinking about learning Go.

Collapse
 
tuhinbar profile image
Tuhin Bar

If you like to say anything to me personally, here is my X account