Go package organization
There are numerous blog posts and articles on the topic of how to organize Go projects, but nearly all of them have missed the point: Go is already telling you how to organize your project. Go doesn’t want you to organize your source code files by any sort of taxonomy; it wants you to organize your source code files by usefulness.
Let’s start with some things you already know. Within a Go project, all your code lives under the top-level module path. Conventionally, this is a “go get”-able repository name like “github.com/subpop/foo”. A module also includes a top-level package name, such as “foo” (or “main” if the project is a program). All Go source code files within this directory must have the same package identifier. It is possible to create additional packages within your module by creating a directory and putting Go source code files in that directory. Likewise, these files must also all have the same package identifier. In this way, Go packages are like tiny, embedded libraries that exist inside your project.
And therein lies the answer. Go packages exist because they are useful not only to the project they exist in, but also to external projects; that’s why they exist as a separate package, importable under a separate import path. A Go package should be useful when imported by itself. If you find that your package is only useful if you also import its parent package, then it should not exist as a separate package.