=============
== sub-pop ==
=============

Go 'pkg' antipattern

I’ve written previously about organizing Go project files. I have observed a trend in Go package organization that strikes me as a clear anti-pattern to project organization. Working under the assertion that Go packages should be useful when imported by themselves, the usage of a ‘pkg’ directory is a clear anti-pattern. Remember the top-level of a Go project is the root of your API. If you want your package to be imported with a path such as “github.com/subpop/foo”, all your code files must exist in the root of the repository. Let’s assume you create a “pkg” directory in your repository and move your code files into it. Now, consumers of your module will import it as:

import "github.com/subpop/foo/pkg"

And using it becomes more puzzling. Is the package identifier now “pkg”? Or is it still “foo”? We’ve now introduced ambiguity for the sake of file organization? Is that a cost worth putting on consumers of your package?

“But no one puts code into ‘pkg’; it’s just for subpackages” you say. This adds needless elements to the import path. Let’s assume you have a couple of packages that you want to export as part of your module’s public API, but they’re useful enough in isolation to bundle into a package. You saw a Github repository claiming to be a “golang-standard”. That repository has a “pkg” subdirectory, so it must be okay, right?

If your repository looks like this:

.
./pkg
./pkg/djset
./pkg/pqueue
./pkg/queue
./pkg/stack

When importing these packages, your imports end up looking like:

import (
    "github.com/subpop/foo/pkg/djset"
    "github.com/subpop/foo/pkg/pqueue"
    "github.com/subpop/foo/pkg/queue"
    "github.com/subpop/foo/pkg/stack"
)

This is frivolous. There’s no advantage to making your package consumers needlessly type “pkg” repeatedly. Drop the “pkg” and your import paths become much more meaningful:

import (
    "github.com/subpop/foo/djset"
    "github.com/subpop/foo/pqueue"
    "github.com/subpop/foo/queue"
    "github.com/subpop/foo/stack"
)

The golang-standards/project-layout cautions readers against unnecessary use of a “pkg” directory. I say go one step further and just don’t use it at all.