
In Go, packages are the fundamental units of code organization. They're used to group related functions, variables, and types together, making it easier to reuse and maintain code.
Packages are identified by a unique name, which must be a valid Go identifier. This name is used to import and use the package in other Go programs.
A package can contain multiple files, but it's common for each file to have a specific purpose, such as main.go for the entry point or utils.go for utility functions. This helps keep the code organized and easy to navigate.
The Go compiler will only look for packages in the GOPATH directory or the current working directory. This means you need to make sure your package is in one of these locations for it to be compiled correctly.
Recommended read: Golang Source Code
Package Structure
In Go, the main package is where you put code that interacts with users of the resulting binary. This typically includes things like command-line argument parsing, user input, config file parsing, exit codes, and signal traps.
The main package is usually kept very simple, with only the essentials. This is because you may have multiple binaries, such as a CLI client and a server, each with its own main package. By keeping the main package minimal, you can easily create unique options for each binary.
Here are some examples of what you might put in the main package:
- Command-line argument parsing
- User input (if it's simple and not part of the core application logic)
- Config file parsing
- Exit codes
- Signal Traps
The Go community doesn't have a single "right" way to structure a codebase. Different projects require different structures, and what works well for one project may not work for another. Even successful projects like mkcert and Kubernetes have different structures due to their unique needs and purposes.
Code Organization
Code Organization is a crucial aspect of Go programming, and it's essential to understand how to structure your code effectively. A package is a collection of source files in the same directory that are compiled together.
In Go, creating a directory creates a new package, and placing a file in that directory makes it part of that package. This is why it's recommended to create a directory only when you have a specific reason to create a new package.
Here's an interesting read: Go vs Golang
A repository contains one or more modules, and a module is a collection of related Go packages that are released together. Each module's path not only serves as an import path prefix for its packages, but also indicates where the go command should look to download it.
A package's import path is its module path joined with its subdirectory within the module. For example, the module github.com/google/go-cmp contains a package in the directory cmp/. That package's import path is github.com/google/go-cmp/cmp.
Packages in the standard library do not have a module path prefix. Commands like go install apply within the context of the module containing the current working directory. If the working directory is not within the example/user/hello module, go install may fail.
Here are some key points to keep in mind when organizing your code:
- Keep related things close to each other – in the same .go file or in the same package.
- Group utility functions that are related to each other and used in multiple places into a single reusable package.
- Define custom struct types and any methods for them directly below the struct declaration in the same .go file.
- Define all routing rules together in a single function or .go file in a web application or API.
Main Package
The main package in a Go application is where the magic happens. It's where your users interact with your binary, and it's what makes your application unique.
Broaden your view: Golang Programs
Command-line argument parsing is a great example of something that belongs in the main package. By parsing arguments here, you can easily create unique options for different use cases, like a CLI client and a server.
A few other things you might find in the main package include user input, config file parsing, exit codes, and signal traps. These are all things that interact with the user or the environment, and keeping them together in one place makes sense.
Here are some examples of what you might find in the main package:
- Command-line argument parsing
- User input (if it's simple and not part of the core application logic)
- Config file parsing
- Exit codes
- Signal Traps
By keeping these things in the main package, you can make your application more flexible and easier to use.
Best Practices
Aim for effective, not perfect. Don't stress too much about making your codebase structure perfect, just focus on making it work effectively enough for your specific project.
Start with a basic layout and just two files: go.mod and main.go. This is perfectly okay, and it's how about half of the new projects the author works on begin.
You might like: Golang Go
Create packages judiciously, only when you have a demonstrable need or good reason to. This will help avoid complexity and import cycle problems.
Here are some scenarios where creating additional packages makes sense:
Getting Started
Starting with a simple project structure is perfectly fine. Begin with just a go.mod and main.go file in the root of your project directory.
You can start with just two files if you're unsure about the project structure. About half of the new projects I work on begin with just these two files.
To compile and run a simple program, choose a module path and create a go.mod file that declares it.
The first statement in a Go source file must be package name. Executable commands must always use package main.
Create a file named hello.go inside that directory containing the basic Go code.
You can build and install that program with the go tool. This command builds the hello command, producing an executable binary.
For convenience, go commands accept paths relative to the working directory. So, in our working directory, the following commands are all equivalent.
For another approach, see: Helloworld Golang
Importing and Testing
To use a package from another directory, create a directory for the package and a file with a name ending in .go, such as reverse.go, with the package's contents.
The ReverseRunes function is exported if it begins with an upper-case letter, making it accessible to other packages that import the morestrings package.
To import the package, modify the original file to use the package name, in this case morestrings.
The go test command and the testing package make up Go's lightweight test framework.
To add a test to the morestrings package, create a file named reverse_test.go with functions named TestXXX that have a signature of func (t *testing.T).
If this caught your attention, see: Golang Use Cases
Importing Packages
To import packages from your module, you need to create a directory for the package and a file with the package's contents.
You can create a directory for the package named $HOME/hello/morestrings, and then a file named reverse.go with the function you want to export.
The function needs to begin with an upper-case letter to be exported, so it can be used in other packages that import your package.
For example, if you have a function named ReverseRunes, it will be exported and can be used in other packages.
To use the package from another program, you need to modify the original program to use the package.
You can do this by importing the package in the original program, and then using the exported function as needed.
The compiled package will be saved in the local build cache, rather than producing an output file.
On a similar theme: Golang Reflect to Call Function in Package
Testing
Go's testing framework is lightweight and easy to use. You can write a test by creating a file with a name ending in _test.go that contains functions named TestXXX with the signature func (t *testing.T).
The test framework runs each such function, and if the function calls a failure function like t.Error or t.Fail, the test is considered failed.
To add a test to the morestrings package, create a file named reverse_test.go in the $HOME/hello/morestrings directory.
Go test is used to run the test, and you can get more information on the testing package by running go help test.
Broaden your view: Golang Rest Api Framework
Featured Images: pexels.com


