Go Fundamentals - Sample
Table of Contents
Chapter 1.3: Folders, Files, and Organization
With a few exceptions, the name of the folder and the name of the package are the same.
For example, if we look at
sound/sound.go, Listing 1.2, the folder name is
sound and the package name is
If we look at
smtp/smtp.go, Listing 1.3, the folder name is
smtp and the package name is
While the folder name and the package name don't always have to match, it is generally a good idea, and idiomatic, to follow this convention. By following this convention, we can easily find the files that belong to a package.
Multiple Packages in a Folder
With rare exceptions, a folder can only contain one package. Let's look at the file structure in Listing 1.4.
Both of the files in Listing 1.4 declare their package name as
Now, let's look at the file structure in Listing 1.6.
Both of the files in Listing 1.6 should declare their package name as
bad, but they do not.
If we look at the file,
a.go, in, Listing 1.7, we can see that the package name is
b.go, Listing 1.8, declares its package name as
We now have two different package names declared in the same folder.
When trying to build the package
bad, we get an error telling us that we can not build the package
bad because two different files have declared different package names.
All files within the same directory/package have to have the same
package name in the file.
File names are less strict than package names. The convention is to use lower-case letters and underscores.
There are a lot of different ways to organize packages in Go. A quick Google search will return numerous blog posts, articles, and conference presentations that discuss the various ways to organize packages in Go. All of these ways have their pros and cons. These patterns are often extracted from one particular use case, that worked well for them in that case. However, not everyone is writing the same applications, and libraries, so there can't be any one best way to organize packages.
When organizing packages you should consider the factors listed in Listing 1.11.
Packages should be singularly focused. For example, if you have a package that contains tools for working with time and for working with HTTP, then that package should be split into two packages, one for time and one for HTTP. Now the packages have a clear, singular purpose.
Package APIs should be clean, simple, and easy to use. Export only the most necessary identifiers, such as types, functions, and variables. It is always easier to expose more of a package's API later than it is to hide it after it's been exposed and is in use.
Package files should be organized in a way that is clear and obvious to the reader. Avoid using one, or two, large files for a package. Instead, break the package into smaller files, with each having a clear purpose.
If we look at the file in Listing 1.12, we can see that the file contains three different type definitions, along with their methods. This file is difficult read and as the file grows, it will become even more difficult to read and maintain.
If, instead, we split the code into more files, Listing 1.13, one for each of the types declared, then we can see that each file is now easier to read and maintain. In addition, the file names are now clear and easy to understand, which makes finding the code your need that much easier.
Organizing your code into smaller files that have clear and specific purposes will make it easier to navigate your project as it grows. It will also make it easier for developers new to your project to find the code they are looking for.