// Or returns the first of its arguments that is not equal to the zero value.
// If no argument is non-zero, it returns the zero value.
func Or[T comparable](vals ...T) T {
var zero T
for _, val := range vals {
if val != zero {
return val
}
}
return zero
}
How do you use it?
The primary use for cmp.Or is for taking strings and returning the first one that isn't blank. For example, searching public open source Go repositories, I found a lot of code online that tries to fetch an environmental variable but return a default value if it's blank. With cmp.Or, this would look like cmp.Or(os.Getenv("SOME_VARIABLE"), "default")
.
Here are a handful of actual uses from a real codebase of mine:
body := cmp.Or(page.Body, rawContent)
name := cmp.Or(jwt.Username(), "Almanack")
credits = append(credits, cmp.Or(credit.Name, credit.Byline))
metadata.InternalID = cmp.Or(
xhtml.InnerText(rows.Value("slug")),
xhtml.InnerText(rows.Value("internal id")),
metadata.InternalID,
)
scope.SetTag("username", cmp.Or(userinfo.Username(), "anonymous"))
currentUl = cmp.Or(
xhtml.Closest(currentUl.Parent, xhtml.WithAtom(atom.Ul)),
currentUl,
)
The other major use for cmp.Or is to use with cmp.Compare to create multipart comparisons:
type Order struct {
Product string
Customer string
Price float64
}
orders := []Order{
{"foo", "alice", 1.00},
{"bar", "bob", 3.00},
{"baz", "carol", 4.00},
{"foo", "alice", 2.00},
{"bar", "carol", 1.00},
{"foo", "bob", 4.00},
}
// Sort by customer first, product second, and last by higher price
slices.SortFunc(orders, func(a, b Order) int {
return cmp.Or(
cmp.Compare(a.Customer, b.Customer),
cmp.Compare(a.Product, b.Product),
cmp.Compare(b.Price, a.Price),
)
})