SPONSORED ADS

Simplifying Your Go Project Layout: Best Practices and Tips

Last Updated Mar 02, 2023

As a curious developer, I often ask myself what the best way to do things is. For example: how to structuring my golang application. Is there a standard way to organize code?

We all know that an optimal project layout can significantly impact the overall quality of the code. In this article, I’m going to show you best practices and tips to simplify your go project that I find helpful for me, and I hope it also helpful for you.

Please keep in mind that these are not official standard defined by the core Go dev team in any way. And do not blindly follow whatever recommendation is here, follow which you found helpful for you.

A single main.go is more than enough

If you just went through the https://tour.golang.org/ and are trying to learn go then standard project layout is an overkill. You should just start with something really simple instead.

I always start with a single main.go file, and as my project grows, I start separating things into their own files.

Organize your code

The first thing I always do when my project grows is separate my binary from my application. main.go become big and has a lot of application logic mixed together.

I've found that the easiest way to fix this is to use a /cmd directory in my project, where each subdirectory is an application binary.

cmd/web/main.go is the main web, while cmd/worker/main.go is for scheduled background jobs.

nodeepshit/
  cmd/
    web/
      main.go
    worker/
      main.go

Then, I look for logic code that is the same in both "cmd/web/main.go" and "cmd/worker/main.go" and move it to its own package. Since these packages are used internal by my project, let's name it internal. In fact the Go tooling recognizes internal as a special path. Packages in the same module (the whole nodeepshit project) can import it as usual but code outside the module (other users clone and use your project) cannot import it.

Put as much as possible to internal, it is more easy to make it private, you can change your mind and public later.

nodeepshit/
  cmd/
    web/
      main.go
    worker/
      main.go
  internal/
    timeago/
      timeago.go
    form/
      form.go
      errors.go

When I change my mind and want a package in my internal to be public (can be imported by users who clone and use my project) I just move them out of internal folder like this.

nodeepshit/
  cmd/
    web/
      main.go
    worker/
      main.go
  timeago/          # this package is not 
      timeago.go    # internal anymore
  internal/
    form/
      form.go
      errors.go

Conclusion

Start simple. Don't complicated stuff.

Hi there. Nodeepshit is a hobby website built to provide free information. There are no chargers to use the website.

If you enjoy our tutorials and examples, please consider supporting us with a cup of beer, we'll use the funds to create additional excellent tutorials.

If you don't want or unable to make a small donation please don't worry - carry on reading and enjoying the website as we explore more tutorials. Have a wonderful day!