Go has no ternary operator. There is no cond ? a : b. The idiomatic replacement is an if statement:
Declare the variable with the default value, then change it in the if. When both branches need work, use if/else:
var fee int
if member {
fee = 0
} else {
fee = computeFee(order)
}
Why Go Left It Out
The Go FAQ answers this directly: the designers had seen the ?: operator used too often to create impenetrably complex expressions, and decided that if/else, while longer, is unquestionably clearer. A language needs only one conditional control flow construct.
In practice the missing operator costs two or three lines per use and removes a whole category of nested expressions like a ? b ? c : d : e.
Returning Early Instead
Inside a function, the cleanest form often skips the variable entirely:
Pulling the condition into a small named function is often the best answer: the call site reads like the ternary you wanted, and the function name documents what the condition means.
Default Values with cmp.Or (Go 1.22)
The most common ternary in other languages is "use this value, or a fallback if it is empty": name ? name : "anonymous", or name || "anonymous" in JavaScript. Go 1.22 added cmp.Or for exactly this. It returns the first argument that is not the zero value of its type:
It treats the zero value as "missing", so it cannot tell "port is 0 on purpose" from "port was not set". When zero is a valid value, use a pointer, a separate bool, or an explicit if.
A Generic If Helper, and Its Trap
With generics (Go 1.18) you can write a function that looks like a ternary:
func If[T any](cond bool, a, b T) T {
if cond {
return a
}
return b
}
status := If(ok, "pass", "fail")
It works for simple values, and some codebases use it. But it is not a ternary operator, and the difference matters. Go evaluates all arguments before calling a function, so both a and b are always computed:
The first call computes both "a" and "b", and the second panics with a nil pointer dereference, even though the condition is false. A real ternary would evaluate only the chosen side. So:
- Never use such a helper when one side dereferences a pointer, indexes a slice, or reads a map entry that may not exist.
- Never use it when one side is expensive or has side effects.
- For cheap, safe values it works, but many Go reviewers will still ask for the plain
if.
You can make the branches lazy by passing functions, If(ok, func() string { return a }, func() string { return b }), but at that point the if statement is shorter.
Other Tricks, and Why to Avoid Them
Map lookup. map[bool]string{true: "yes", false: "no"}[ok] works, builds and hashes into a map on every evaluation, and evaluates both values. It is a curiosity, not an idiom.
Immediately invoked function. An anonymous function called in place gives you an expression:
label := func() string {
if n > 0 {
return "positive"
}
return "non-positive"
}()
This does evaluate lazily, and it occasionally helps inside a composite literal where a statement cannot go. Most of the time, computing the value in a variable just before the literal is clearer.
Choosing a Replacement
| Situation | Use |
|---|---|
| Pick between two values | default value, then if |
| Both branches need computation | if/else |
| Value decides the function's result | early return |
| Fallback when a value is empty | cmp.Or(value, fallback) |
| Three or more cases | switch |
| Repeated condition with a meaning | a small named function |
Proposals to add a conditional expression come up regularly on Go's issue tracker and have been declined so far. Write the if.
Frequently Asked Questions
Does Go have a ternary operator?
No. Go has no cond ? a : b expression. The Go FAQ says the designers left it out because it is too often used to build expressions that are hard to read. Use an if/else statement instead.
How do I write a one-line conditional assignment in Go?
Assign the default first, then override it:
label := "odd"
if n%2 == 0 {
label = "even"
}
That is the idiomatic replacement. gofmt will not put an if body on one line, so it always takes at least three lines.
Can I write a generic ternary function in Go?
Yes: func If[T any](cond bool, a, b T) T { if cond { return a }; return b }. The catch is that Go evaluates every argument before calling a function, so both a and b are computed. If(p != nil, p.Name, "") still dereferences a nil p and panics. A real ternary would evaluate only one side.
How do I set a default value if a string is empty in Go?
Since Go 1.22, cmp.Or(name, "anonymous") returns the first argument that is not the zero value, so it gives name unless name is "". It works for any comparable type, and like any function call it evaluates all its arguments.