On Go Package Structure

jrwren profile image Jay R. Wren ・2 min read

Go is getting more and more popular and as it does, some of the information out there about it is less and less idiomatic Go. It is great that Go is getting so popular. It is dangerous that there is more and more misinformation and bad advice out there.

One of the common areas of bad or poor advice I see out there is regarding project structure. This seems to be experience programmers projecting their past experience and trying to make Go into something that it is not.

In #reviews on the Gophers slack, I commented on someones request for review simply by saying "sooo many packages. would be more readable with everything in one package IMO".

Their response was that they tried to use many packages to simulate C#'s namespaces. This is my response:

Go doesn’t have namespaces for a reason. I recommend trying to let go of some aspects of C#.

golang-standards/project-layout is bad advice. I recommend not following it. Instead, https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1 is much better.

If you are writing the code only for yourself, then none of this matters. If you are writing the code on a team with others, then it becomes more important.

The big difference with C# namespaces, or even projects/dll is that in Go, circular references are not allowed. So if you split things into packages when they don’t need to be reused, you will someday find yourself wanting to import something else and will create a cycle, and then you have to restructure things, as you should have to start with, to avoid the cycle.

Another important difference between Go packages and C# namespaces is that in C#, many namespaces can be in a single project/dll. The namespacing is orthogonal to the compilation unit. Trying to use Go packages as a namespace conflates the two and confuses things.

The best guidance for this is all over the standard library. e.g. net/http is all in one package. There isn’t net/http/server and net/http/request and net/http/response, even though often only one or some of them are used.

Posted on by:


markdown guide