Go Your Own Way: Customizing Go with Environment Variables

Sourav Choudhary
9 min readOct 3, 2023

Environment variables in Go, often referred to as Go-specific environment variables, are variables that influence the behavior of Go applications or are specific to the Go runtime environment.

These variables can be set to configure various aspects of your Go development environment, runtime, and build process. In this comprehensive guide, we’ll explore the most important Go-specific environment variables, their significance, and how to use them effectively.

1. GOOS and GOARCH

Purpose: These variables are used when cross-compiling Go code for different operating systems and architectures.

Usage: Set GOOS to your target operating system (e.g., "linux," "windows," "darwin") and GOARCH to your target architecture (e.g., "amd64," "arm") when running the go build or go install command.

Benefits: Cross-Platform Compatibility — These variables allow you to compile your Go code for different operating systems and architectures, increasing the portability of your applications.

# Cross-compile for Linux on a Windows machine (GOOS=linux, GOARCH=amd64)
GOOS=linux GOARCH=amd64 go build -o myapp-linux main.go

2. GOPATH and GO111MODULE

Purpose: These variables are used for managing dependencies and project layout.

Usage: GOPATH specifies the workspace path. However, it's less relevant in Go module-enabled projects.

GO111MODULE controls Go modules' behavior, and it can be set to "on," "off," or "auto."

When to Use:

GOPATH is typically used in non-module projects for specifying the workspace location.

GO111MODULE is used to enable or disable Go modules.

Use Go modules for modern dependency management.

Benefits:

Dependency Management: GOPATH (in non-module projects) and GO111MODULE (in module-enabled projects) are crucial for managing dependencies effectively.

Versioning: Go modules, controlled by GO111MODULE, enable versioned dependency management, reducing dependency-related issues.

# Enable Go modules (GO111MODULE=on)
GO111MODULE=on go run main.go

3. GOCACHE and GOTMPDIR

Purpose: These variables manage Go’s build cache and temporary file locations.

Usage: Customize GOCACHE and GOTMPDIR to specify cache and temporary file storage.

Benefits :Customizing cache and temporary storage locations to improve build performance.

Managing build artifacts efficiently.

# Customize the cache directory
GOCACHE=/path/to/cache GOTMPDIR=/path/to/temp go build main.go

How GOCACHE improve build performance ??
basically GoCACHE stores and manages compiled package objects to improve build performance. It serves as a cache for intermediate build artifacts, preventing redundant compilation and improving the efficiency of the build process.

Here’s how the Go build cache works:

1. Compilation: When you build a Go application or package, the Go compiler compiles the source code into object files (with a `.o` extension).

2. Caching: The Go build cache stores these compiled object files, along with related metadata, in a cache directory. By default, this cache directory is located in the user’s home directory (`$HOME/go/pkg`). However, you can customize the cache location using the `GOCACHE` environment variable.

3. Reuse: The next time you build the same package or import the same dependency, Go checks the cache directory to see if the compiled object files and metadata are already present. If they are, Go reuses these cached files instead of recompiling the source code. This significantly speeds up the build process, especially for large projects with many dependencies.

4. Invalidation: The cache is aware of changes in source code or build flags. If anything has changed, the cache is invalidated for that specific build, and Go will recompile the affected parts of the code.

The Go build cache offers several benefits:

- Faster Builds: By reusing cached object files, Go builds are much faster, especially in large projects or in scenarios where dependencies don’t change frequently.

- Reduced CPU and Memory Usage: Caching reduces the CPU and memory resources required for compiling the same code repeatedly.

- Consistent Builds: The cache ensures that the same code always produces the same compiled results, improving build consistency.

- Isolation: Cached files are stored separately for different Go versions and different build configurations, preventing conflicts.

- Customization: You can customize the cache location and other cache-related settings using environment variables like `GOCACHE`.

What are build artifacts ??

Build artifacts are the files and outputs generated as a result of compiling and building a software project. These artifacts are created during the build process and typically include:

1. Executable Binaries: For compiled languages like Go, C, C++, and Rust, the primary build artifact is the executable binary. This is the file that contains the machine code instructions that the computer’s processor can execute. It’s the final output of the build process, representing the compiled version of your source code that can be run as a program.

2. Library Files: In some cases, especially in languages like C and C++, build artifacts include shared libraries (e.g., DLLs on Windows, shared objects on Linux) or static libraries (e.g., .a files on Unix-based systems). These libraries contain reusable code that can be linked to other programs or libraries.

3. Intermediate Files: During the compilation process, various intermediate files are generated. These files are not meant to be directly executed but are crucial for creating the final executable. Examples include object files (with .o or .obj extensions) and preprocessed source code.

4. Configuration Files: In certain build systems, configuration files may be generated as build artifacts. These files can contain information about build settings, environment variables, or metadata related to the build.

5. Documentation: Build processes can also generate documentation as artifacts. This can include API documentation, user manuals, or any other documentation associated with the software project.

6. Test Results: When running tests as part of the build process, the results of those tests can be considered build artifacts. These results may include test logs, reports, and coverage information.

7. Packaged Distributions: In some cases, the build process produces packaged distributions of the software, such as installer files (e.g., .msi on Windows, .dmg on macOS), tarballs, zip files, or container images. These distributions are often used for deployment and distribution purposes.

Build artifacts are essential in the software development lifecycle because they represent the tangible output of the development and build processes. These artifacts are typically stored, versioned, and distributed as part of software releases. They allow developers to share, deploy, and run their software on various environments, making them a critical component of software development and delivery.

— — — — — — — — — — — — — — — — — — — — — — — — — -

4. GOBIN and GOPROXY

  • GOBIN: This environment variable defines the directory where Go binaries (executables) are installed when you use the go install command. It should be added to your system's PATH to execute these binaries conveniently.
  • GOPROXY: This variable specifies the Go module proxy server used for downloading module dependencies. It can be set to a custom proxy or one of the publicly available ones like "https://proxy.golang.org."

Benefits:

  • Binary Management: GOBIN lets you specify a custom directory for storing compiled Go binaries.
  • Proxy Control: GOPROXY helps manage the source of Go module downloads, enhancing security and reliability.
GOBIN=/path/to/bin GOPROXY=https://proxy.golang.org go install main.go

More about GOPROXY:

1. Purpose: `GOPROXY` specifies the proxy server that Go uses to retrieve module dependencies. A module proxy caches and serves modules, making it faster and more reliable to download dependencies, especially in environments with limited internet access or where certain dependencies may be unavailable due to network restrictions.

2. Values: `GOPROXY` can be set to various values, depending on your requirements:
Direct URL: You can set `GOPROXY` to the URL of a specific module proxy server, e.g., `GOPROXY=https://proxy.example.com`.
Multiple Proxies: You can also specify multiple proxy servers, separated by commas. Go will attempt to download modules from each in order until it succeeds, e.g., `GOPROXY=https://proxy1.example.com,https://proxy2.example.com`.

3. Public Proxies: Several public module proxy servers are available for general use, making it easy to get started with Go modules. The official Go proxy, `https://proxy.golang.org`, is often used by default. Other public proxies include JFrog’s JCenter, Google’s Cloud Source Repositories, and others.

4. Private Proxies: Organizations and companies can set up their private module proxy servers to control access to internal dependencies and ensure faster, more reliable builds. Private proxies can be specified using `GOPROXY`.

5. Fallback Behavior: If `GOPROXY` is set and a module cannot be found on the specified proxy server(s), Go will fall back to checking the public proxy (`https://proxy.golang.org`) and the original module source (e.g., a Git repository or a version control system).

6. Security: Using a trusted proxy server (either public or private) adds a layer of security to dependency management. Proxy servers can validate modules and ensure that they have not been tampered with, protecting your project from potential security risks.

7. Offline Mode: By setting `GOPROXY=off`, you can disable the use of any proxy server, forcing Go to use only the local filesystem for module resolution. This can be useful for working offline or in situations where network access is restricted.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — -

5. GOFLAGS

Purpose: This variable allows you to specify additional flags for the go command.

Usage: Set GOFLAGS to include additional command-line flags when running go commands.

  1. Enabling Verbose Output:
GOFLAGS=-v go build main.go

This command compiles the `main.go` program with the `-v` flag, which stands for “verbose.” It provides detailed information about the build process, including which files are being compiled and linked.

2. Setting Output Directory:

GOFLAGS=-o myapp go build main.go

Here, the `-o` flag is used to specify the output file’s name as `myapp`. This can be handy when you want to customize the name of the generated binary.

3. Building with Specific Tags:

GOFLAGS=-tags=mytag go build main.go

You can use the `-tags` flag to build your Go program with specific build tags. Build tags are a way to include or exclude certain parts of your code during compilation based on conditions defined in your source code.

4. Cross-Compiling with `GOOS` and `GOARCH`:

GOFLAGS="-v -ldflags '-s -w' -trimpath" GOOS=linux GOARCH=amd64 go build main.go

In this example, `GOFLAGS` is used to pass a combination of flags to customize the build process. It includes the `-v` flag for verbose output, `-ldflags` to specify linker flags, and `-trimpath` to trim the source path. Additionally, `GOOS` and `GOARCH` are set to cross-compile the program for Linux on an AMD64 architecture.

5. Modifying Build Mode:

GOFLAGS="-buildmode=shared" go build main.go

Here, `GOFLAGS` is used to specify the build mode as “shared.” This can be useful when you want to create a shared library or plugin using Go.

6. Running Tests with Parallelism:

GOFLAGS="-p 2" go test ./…

You can control the parallelism of your Go test runs using the `-p` flag. In this example, `GOFLAGS` is set to run tests with a maximum of 2 parallel processes.

7. Running Benchmarks with Custom Timing:

GOFLAGS="-benchtime=2s" go test -bench=. ./…

The `-benchtime` flag allows you to specify the duration for which benchmark tests should run. Here, `GOFLAGS` is used to set the benchmark time to 2 seconds.

8. Using Custom Environment Variables:

GOFLAGS="GOARCH=arm64 GOOS=linux" go build main.go

You can use `GOFLAGS` to set custom environment variables for the Go build process. In this case, it specifies the `GOARCH` and `GOOS` variables to cross-compile for ARM64 architecture on Linux.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

6. GOENV

Purpose: This variable points to a directory containing Go-specific environment configuration files.

Usage: Use GOENV to centralize Go environment settings across projects.

When to Use:

  • When you want to maintain consistent environment settings across multiple projects.
  • Managing project-specific configurations.
# Use a custom directory for Go environment configuration files
GOENV=/path/to/goenv-config go run main.go

7. GOTRACEBACK

Purpose: This variable controls the amount of output generated when a Go program panics.

Usage: Set GOTRACEBACK to control the level of detail in panic traces.

When to Use:

  • Debugging and diagnosing panics or unexpected program crashes.
  • Controlling the verbosity of panic output.
# Enable detailed panic traces
GOTRACEBACK=all go run main.go

8. GODEBUG

Purpose: This variable enables various debugging features in the Go runtime.

Usage: Set GODEBUG to enable specific debugging options in the Go runtime.

When to Use:

  • Diagnosing performance issues, memory allocation, and garbage collection.
  • Debugging and profiling Go applications.

1. Enabling Debug Output:

to enable garbage collection tracing:

GODEBUG=gctrace=1 go run main.go

This will print detailed garbage collection information during program execution.

2. Memory Allocation Tracking:

To track memory allocations, you can set the `allocfreetrace` flag:

GODEBUG=allocfreetrace=1 go run main.go

This will show memory allocation and deallocation details.

3. Controlling Goroutine Stacks:

You can control the amount of information printed when a program crashes by setting the `gctraceback` flag:

GODEBUG=gctraceback=1 go run main.go

This will provide additional information in the panic trace.

4. Profiler Settings:

Various profilers can be controlled with `GODEBUG`. For example, to enable the CPU profiler:

GODEBUG=1 go run main.go

This will generate CPU profiling information.

— — — — — — — — — — — — — — — — — — — — — — — — -

If you read uptill now, then I hope you liked this article and if you like this article then please Clap, as it motivates me to help the community.

Please comment if you found any discrepancy in this article or if you have any question related to this article.

Thank You for your time.

Connect me on LinkedIn 🤝

--

--