structuring golang projects (uncompleted)


Structuring Golang Projects

Who never ask yourself about what is the best way to create a new project? Should I use the Hexagonal, DDD, Clean and these others fancy architectures? Go has a different style, but when you are a newcomer in the language, probably you don’t had the enough time to consume and read all the good repositories and resources to drive your decisions. This post is a collection of my thoughts and experiences about how to structure Go projects. With name conventions, package organization, and some tips to make your codebase more readable and maintainable.

Dilemmas

prs
  • Should I put everything together?
  • Start small and grow?
  • What is the β€œGo way”?

What is non-negotiable?

  • Consistency across the codebase
  • Easy to change, loosely coupled
  • Easy to test, that implies decoupled package with clear duties and goals
  • Design reflect how the software works

Grouping

Listing some feasible approaches to organize your golang codebase.

Flat

.
β”œβ”€β”€ cmd
β”‚   └── main.go
└── flat
    β”œβ”€β”€ disk.go
    β”œβ”€β”€ http.go
    β”œβ”€β”€ inmem.go
    β”œβ”€β”€ lamps.go
    β”œβ”€β”€ output.txt
    └── processes.go

At least for me, in a first glance, seems a good approach. Everything is together, easy to find, easy to change. But, obviously, when the projects grow, this approach will become a mess.

By Function/Layer

By Context

.
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ Makefile
β”œβ”€β”€ cmd
β”‚   └── appname
β”‚       └── main.go
β”œβ”€β”€ compose.yaml
β”œβ”€β”€ domain1.go
β”œβ”€β”€ domain2.go
β”œβ”€β”€ domain3.go
β”œβ”€β”€ firestore
β”‚   β”œβ”€β”€ domain1.go
β”‚   └── firestore.go
β”œβ”€β”€ http
β”‚   β”œβ”€β”€ docs
β”‚   β”‚   └── swagger.yaml
β”‚   β”œβ”€β”€ domain1.go
β”‚   └── http.go
β”œβ”€β”€ mock
β”‚   └── domain1.go
β”œβ”€β”€ output.txt
β”œβ”€β”€ postgres
β”‚   β”œβ”€β”€ domain1.go
β”‚   β”œβ”€β”€ migrations
β”‚   β”‚   β”œβ”€β”€ migration1-down.sql
β”‚   β”‚   └── migration1-up.sql
β”‚   └── postgres.go
└── pubsub
    β”œβ”€β”€ domain3.go
    └── pubsub.go

Package organization

This was the best definition of how to organize packages in the golang style without screwing up the codebase. It’s a 2 definition rule that shape the whole codebase.

Domain Types

The domain types are the ones that represent the business logic of the application.

Service

The service packages are the ones that will operate on the domain types.

Names and Conventions

Mock

Important Resources