Organizing Go Code

Hi,

Im coming from the .NET world and am interested in the Topic Organizing Code in the Go Ecosystem.
For now, Interfaces. If it comes to something more, I would like to update this Topic.

Interfaces

I wonder what the go way or a good practice is, when it comes to interfaces.

Example:

type Settings struct{}

type Controller interface {
  Run(Settings)
}

I keep Interfaces inside a package called contract. Where do you define the type Settings?

package:

  • contract
  • Right now, type Settings is defined here
  • settings
  • model
  • There could be a circular dependency between model and contract
  • Maybe model should not import contract at all?
  • …?

A good practice (not only in go) is to group code into packages by provided functioality (e.g. user, auth, shoppingcart) not by layers (e.g. model, controllers, views). Related code should be placed into one package.

When you start organizing code this way you will notice that cyclic dependencies between packages disapear and number of methods/types that need to be public reduces.

6 Likes

so you mean for one feature one package? what is about general components? what happens, if you have one big feature. about 1k loc, would you separate into layers?

what Konstantin said was: don’t organize code by type of code. When you organize into packages “db”, “dao”, “business”, “service” (a common old-fashioned patern in Java/.NET world), then you’ll have to touch each package as you add more functionality to your app. If your packages instead reflect separate functional pieces of application (“import/export”, “reporting”, “projects”), it’s much easier to understand how a certain feature works.

Of course, you always will need those generic packages that are supporting several user features, e.g. logging setup or common code for rest endpoints.

Long story short - don’t over think it. Put stuff in one package, multiple files while it’s still taking shape, once it gets too big, maybe some of your files will look like they belong to a different package of their own.

2 Likes

thanks for your answers @Viktoras_Makauskas and @kostya_sh, i will try that

A package can have multiple files, so 1k LOC in a single package wouldn’t be absurd. Most of the standard library packages exceed that.

I believe code should be organised into packages names for what the package provides, not what it contains. This can sometimes be subtle, but usually not.

For example, http, provides http clients and servers.

As a counter example, package utils is a poor name, yes it provides utilities, but you have no idea what from the name, in truth this package is named for what it contains.

If your project is a library, it should contain one package (excluding examples and possibly utility commands), if it contains more packages, that is a sign that the library is trying to do too many things.

Prefer to avoid multiple packages by default, only split code by package if there is a clear separation of concerns. In my experience many frustrations with complex and possibly circular package structures are the result of too many packages in a project.

5 Likes

I’ve always found Bolt (GitHub - boltdb/bolt: An embedded key/value database for Go.) to be a good example of this: a powerful library that doesn’t seek to split itself into 3-4 sub-packages.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.