How to Use cmp.Or in Go for Default Value Chains
The cmp.Or function from golang.org/x/exp/cmp returns the first non-zero value from a list of arguments, eliminating verbose conditional blocks when implementing configuration fallbacks and optional parameter defaults.
Managing configuration in Go often requires checking multiple sources—command-line flags, environment variables, and hard-coded defaults—before settling on a value. The JetBrains/go-modern-guidelines repository explicitly recommends using cmp.Or to streamline these default value chains into concise, readable expressions. This helper function evaluates arguments left-to-right and returns the first one that differs from its type's zero value.
Understanding cmp.Or in Go
Core Functionality
cmp.Or is a generic utility that accepts any number of comparable arguments and returns the first non-zero value. If all arguments represent their type's zero value—such as empty strings, zero integers, or nil pointers—the function returns the last argument.
According to the source at internal/guidelines/guidelines_test.go line 16, the official guideline states: "Use cmp.Or to pick the first non-zero value from a fallback chain." This recommendation appears in the test file that validates the CLI output descriptions for the guideline tool, confirming its status as a modern Go best practice.
Comparison with Traditional Approaches
Without cmp.Or, developers typically write repetitive if statements to check each candidate:
var mode string
if flagValue != "" {
mode = flagValue
} else if envValue != "" {
mode = envValue
} else {
mode = defaultValue
}
The cmp.Or function collapses this pattern into a single expression while maintaining type safety through Go generics.
Implementing Default Value Chains with cmp.Or
String Configuration Fallbacks
When configuring application settings from multiple sources, cmp.Or evaluates possibilities in priority order. The following example demonstrates a typical three-tier fallback: command-line flag, environment variable, and hard-coded default:
package main
import (
"fmt"
"golang.org/x/exp/cmp"
)
func main() {
var (
flagValue string // empty because flag not set
envValue string = "prod"
defaultValue = "dev"
)
// Returns "prod" - the first non-zero string
mode := cmp.Or(flagValue, envValue, defaultValue)
fmt.Println("Selected mode:", mode)
}
Numeric Priority Selection
The function works identically for numeric types, making it ideal for port selections, timeout configurations, and retry counts:
var (
override int // zero because not overridden
envPort int = 8080
defPort = 80
)
port := cmp.Or(override, envPort, defPort) // Returns 8080
Pointer and Interface Defaults
For pointers, cmp.Or treats nil as the zero value, returning the first non-nil pointer. This behavior supports dependency injection and optional override patterns:
var (
ptrA *int // nil
ptrB = new(int)
)
*ptrB = 42
selectedPtr := cmp.Or(ptrA, ptrB) // Returns ptrB pointing to 42
fmt.Println("Selected value:", *selectedPtr)
Installation and Module Requirements
The cmp.Or function resides in the experimental extensions module. As referenced in the repository's go.mod file, you must add the dependency before use:
go get golang.org/x/exp/cmp
Then import the package in your Go files:
import "golang.org/x/exp/cmp"
The internal/guidelines/guidelines.go file generates the CLI recommendations that include this dependency, indicating its acceptance in the modern Go ecosystem despite its experimental location outside the standard library.
Summary
cmp.Orprovides a concise mechanism for default value chains by returning the first non-zero argument from a variadic list.- The JetBrains/go-modern-guidelines explicitly recommends this pattern in
internal/guidelines/guidelines_test.gofor handling configuration fallbacks and optional parameters. - It eliminates verbose
if/elseblocks when checking flags, environment variables, and hard-coded defaults in priority order. - The function supports all comparable types, including strings, integers, and pointers, with nil treated as a zero value.
- Available through
golang.org/x/exp/cmp, it requires adding the experimental module to your project's dependencies.
Frequently Asked Questions
What is the difference between cmp.Or and coalesce functions in other languages?
Unlike SQL-style COALESCE which specifically handles NULL, cmp.Or compares against the Go zero value for the given type. This includes empty strings, zero integers, and nil pointers, making it type-safe through Go generics while serving the same logical purpose of returning the first "meaningful" value in a sequence.
Can cmp.Or be used with custom struct types?
Yes, provided the custom type is comparable and you can define what constitutes its zero value. However, for complex structs, you should use pointers where nil represents "unset," as cmp.Or performs a direct comparison against the type's zero value rather than invoking an IsZero() method.
Is cmp.Or part of the Go standard library?
No, cmp.Or currently resides in golang.org/x/exp/cmp, the experimental extensions repository. The go.mod file in JetBrains/go-modern-guidelines tracks this dependency separately from standard library packages, though the guidelines suggest it as a modern best practice for default value chains.
How does cmp.Or handle boolean values?
cmp.Or treats false as the zero value for booleans, meaning it will skip false arguments and return the first true value. If you need to distinguish between an unset boolean and an explicit false, use a pointer to bool (*bool) where nil represents unset and false represents explicitly disabled.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →