Packaging Go code using Version Control Systems (VCS) is the process of organizing and distributing Go code, making it easier to share, version, and install. In this topic, we will thoroughly examine the key aspects and tools required for efficient Go code packaging, including using GOPATH and GOBIN environment variables, employing the go get and go install commands, and adhering to Semantic Versioning principles. Understanding these aspects will provide a foundation for creating reliable and stable software ready for integration and application in various projects.
Working with GOPATH and GOBIN
Let's start with a short definition of these variables and how to set them up.
GOPATH is an environment variable that points to your working directory for Go projects. It plays a crucial role in the structure of Go projects as it determines where Go will search for and install packages and store compiled binary files.
In the workspace defined by GOPATH, there are usually three main folders:
src: This stores the source code.
bin: Contains executable files.
pkg: Contains compiled packages, allowing the reuse of binary versions of packages, which speeds up the build process.
To set up GOPATH, open your terminal and use the command for your operating system:
For Linux or macOS:
export GOPATH=$HOME/goFor Windows:
set GOPATH=C:\goTo permanently save this variable, add it to your shell's configuration file (e.g., .bashrc or .zshrc for Linux/macOS or Environment Variables in Windows).
To check the current value of GOPATH, enter in the terminal:
echo $GOPATHThis command will display the current path set for GOPATH, for example: /Users/<your username>/go
GOBIN is an environment variable that points to the directory where executable files will be stored. If GOBIN is not set, executable files are placed by default in a subdirectory bin inside GOPATH.
Setting GOBIN allows you to define a separate place to store all executable files, which can be helpful when managing binary files for large projects or when working on many small projects.
To set GOBIN, open your terminal and use the command for your operating system: For Linux or macOS:
export GOBIN=$HOME/go/binFor Windows:
set GOBIN=C:\go\binSimilar to GOPATH, you can add the GOBIN variable to your shell's configuration file or the Windows environment variables to save the settings.
To check the current value of GOBIN, enter in the terminal:
echo $GOBINThis will show you the current path set for GOBIN.
It's important to note that, starting with Go 1.11, the use of GOPATH has become less common, and it's recommended to use Go Modules for dependency management. However, understanding and correctly setting GOPATH is still important for grasping Go fundamentals and for working with old projects when Go modules are not used.
Go tools for code packaging
go get command
Often, during the development of your Go application, you will need to use ready-made libraries; this could be, for example, a library for working with a web framework or tools for database operations. The go get command lets you download and integrate such packages into your project.
go get is a command used to download and install external packages and dependencies into your Go project. It downloads the required package and automatically adds it to your project, making it available for use.
Suppose you need to install a package to work with the Gin web framework. Execute the following command in the terminal:
go get github.com/gin-gonic/ginWhen you call the go get command, the following happens:
go getchecks for the presence of the specified package in your local cache.If the package is unavailable locally,
go getaccesses the remote repository (in this case, GitHub) and downloads the necessary package.After downloading, it creates the corresponding directory structure inside
GOPATH/src— in this case,GOPATH/src/github.com/gin-gonic/gin— and places the package's source code there.
Note that in the context of Go Modules, go get is also used to update dependencies in the go.mod file, thus managing the versions of the packages used. go get updates the dependency files in your project and downloads the necessary packages into the folder defined for modules, regardless of GOPATH. In the traditional GOPATH system, go get places the downloaded packages in the src folder inside your GOPATH, creating the corresponding directory structure for each package. Thus, go get directly affects only the contents of the src folder inside your GOPATH.
Fetching a specific version of a package: With the advent of modules in Go, you can also specify a particular package version to install; this is done using version tagging. For example, if you need version 1.6.3 of the Gin framework, you can use the command:
go get github.com/gin-gonic/[email protected]This command downloads and installs the specified version of the Gin package.
go install command
After you have developed your package or application, the next step will be its compilation and installation for subsequent use. Here, the go install command comes to the rescue. The go install command compiles your package and creates an executable file, placing it in the directory specified in the GOBIN environment variable or in the bin directory inside GOPATH if GOBIN is not set.
Suppose you have created an application and want to compile and install it for global use. Execute the following command in the terminal:
go install myappWhen this command is called, the following happens:
go installcompiles your application's source code, creating an executable file.This executable file is then moved to the directory defined in
GOBINor toGOPATH/bin, where it becomes available for execution from the command line.
When you build projects in Go, the compiler stores compiled versions of dependencies in the GOPATH/pkg folder. This allows Go to quickly reuse these binary files in subsequent builds, reducing compilation time.
With the use of Go Modules, compiled packages are cached in a separate module cache system rather than in GOPATH/pkg.
Semantic Versioning (SemVer)
Semantic Versioning (SemVer) is a standardized system for managing software versions. Its goal is to simplify the process of determining the levels of changes between consecutive releases and allow developers to more easily adapt to new versions and better understand what changes each new version contains and the potential risks when updating dependencies.
This system is based on three primary components: MAJOR, MINOR, and PATCH, which denote the levels of changes in the code. Let's delve into what these levels mean and how they are used.
SemVer Versioning Template. A version in the SemVer format looks like MAJOR.MINOR.PATCH, where:
The MAJOR version (
1in1.3.2) increases when incompatible changes are made to the API; this means that the changes are significant enough that they may require changes in the code that depend on this component.The MINOR version (
3in1.3.2) increases when new functionality is added while maintaining backward compatibility; this means that new features and improvements have been added, but these changes do not break existing functionality.The PATCH version (
2in1.3.2) increases when backward-compatible bug fixes are made. These are minor changes aimed at fixing bugs without affecting the overall functionality or structure of the API.
Additional SemVer Specifications. Pre-release versions are denoted by adding a hyphen and additional identifiers immediately after the PATCH version, for example, 1.0.0-alpha; this indicates that the version is at an early stage of development and may not include all the features planned for the final release. Build metadata is added after a plus sign, for example, 1.0.0-alpha+build.45. Build metadata may include build number or other information useful during program building or testing.
Examples of Using SemVer:
You release a new project. The initial version will be
1.0.0.You added new functionality that does not break the existing API. The new version will be
1.1.0.You fixed a bug that does not affect the API. The new version will be
1.1.1.You made significant changes that could affect existing integrations. The new version will be
2.0.0.
How to add a Version to a Go Project? If your project is stored in the Git version control system, you can use Git tags to mark releases; this can be done using the git tag command:
git tag -a v1.0.0 -m "Release version 1.0.0"Then, push the tag to the remote repository:
git push origin v1.0.0Git tags help other developers easily find specific versions of your code. When you make changes to your project that require a version number update (bug fixes, adding functionality, or incompatible API changes), you need to create a new Git tag with the updated version:
git tag -a v1.1.0 -m "Release version 1.1.0"
git push origin v1.1.0Always follow the principles of SemVer when updating versions. Make sure all changes are well-tested before updating the version. If you frequently update versions, use automated tools or scripts to simplify this process. It's important to note that version management is not just about updating a number in a file but a process that should be accompanied by adequate testing, documentation, and, if necessary, communication with your users or clients.
Conclusion
In this topic, you have learned:
How to set and modify the
GOPATHandGOBINenvironment variables, as well as understand their role in the structure of Go projects.The use of the
go getcommand for managing dependencies and installing external packages, and discussed the changes in its use with the introduction of Go Modules.The
go installcommand for compiling and installing Go programs and packages.The Semantic Versioning (SemVer) pattern and its application for denoting project versions, including pre-releases and build metadata.
These insights will help you better navigate Go's packaging and dependency management processes and correctly denote and update the versions of your projects.