Operators and expressions¶
The complete list¶
Arithmetic¶
Comparison¶
Comparison always yields a bool.
Logical (boolean)¶
Short-circuit, like Python. Operands must be bool — no implicit truthy conversion.
Bitwise¶
& // AND
| // OR
^ // XOR (also unary NOT)
&^ // AND NOT — Go-specific, clears bits
<< // left shift
>> // right shift
Compound assignment¶
Address-of / dereference¶
Integer overflow wraps¶
Integer overflow uses two's complement arithmetic — no undefined behavior, no panic.
If you need overflow detection, use the math/bits package's Add64/Mul64/etc., or check ranges manually before arithmetic.
From Python: Python's
intgrows without bound. Go integers are fixed-width and wrap. For arbitrary precision you reach formath/big.Int.
Integer division truncates toward zero¶
fmt.Println(7 / 2) // 3
fmt.Println(-7 / 2) // -3 (toward zero, not toward -infinity)
fmt.Println(7 % 2) // 1
fmt.Println(-7 % 2) // -1
From Python: Python 3's
/always returns float (7 / 2 == 3.5); use//for integer floor division (-7 // 2 == -4). Go's/is integer division when both operands are integers, and truncates toward zero like C.
No exponentiation operator¶
Go has no **. Use math.Pow:
import "math"
fmt.Println(math.Pow(2, 10)) // 1024 — float64
// For integer powers of 2, use a shift:
fmt.Println(1 << 10) // 1024
No ternary operator¶
The community decided readability beats brevity. Use if/else or a helper:
// Python: status := "even" if n%2 == 0 else "odd"
var status string
if n%2 == 0 {
status = "even"
} else {
status = "odd"
}
If you really want a one-liner, write a tiny generic helper:
func If[T any](cond bool, a, b T) T {
if cond { return a }
return b
}
status := If(n%2 == 0, "even", "odd")
But most Go code just uses the four-line if/else. Don't fight the language.
++ and -- are statements, not expressions¶
i++ // ok — statement
j-- // ok — statement
x := i++ // compile error: i++ is not an expression
if i++ > 10 {} // compile error
You can never use i++ inside an expression. And there is no ++i / --i prefix form.
&^ — AND NOT (bit clear)¶
Unique to Go. a &^ b is equivalent to a & (^b) — clears the bits in a that are set in b.
const (
Readable = 1 << 0 // 0b001
Writable = 1 << 1 // 0b010
Executable = 1 << 2 // 0b100
)
perms := Readable | Writable | Executable // 0b111
perms = perms &^ Writable // 0b101 — write bit cleared
String concatenation¶
s := "hello" + ", " + "world" // works, but allocates per +
s := fmt.Sprintf("%s, %s", "hello", "world")
import "strings"
s := strings.Join([]string{"hello", "world"}, ", ")
// For many concatenations in a loop, use a Builder:
var b strings.Builder
for _, w := range words {
b.WriteString(w)
b.WriteString(" ")
}
result := b.String()
Concatenating with + in a tight loop is O(n²) — each + copies the whole prefix. strings.Builder is O(n).
From Python: ≈ the
+vs''.join(...)discussion. Same advice: use the builder for loops.
Operator precedence¶
Five levels, lowest to highest:
Unary operators (!, -, ^, *, &, <-) bind tighter than any binary operator.
When in doubt, parenthesize. Code-reviewers prefer explicit parens over relying on the table.
Comparison gotchas¶
- Floats compare exactly, but with a twist.
0.1 + 0.2 == 0.3written as bare literals istrue— Go evaluates untyped constant expressions at compile time with arbitrary precision, so no IEEE 754 rounding ever happens. Once the same numbers live infloat64variables, rounding kicks in and the answer flips:
fmt.Println(0.1 + 0.2 == 0.3) // true (untyped constants)
var a, b, c float64 = 0.1, 0.2, 0.3
fmt.Println(a + b == c) // false (float64 variables)
Use an epsilon comparison whenever you're comparing float32/float64 variables.
- Strings compare byte-by-byte (lexicographic). "a" < "b" is true.
- Slices, maps, functions are not comparable with ==/!= — only against nil. Use reflect.DeepEqual or a hand-written check.
Sources¶
- Operators — go.dev/ref/spec#Operators
- Arithmetic operators — go.dev/ref/spec#Arithmetic_operators
- Comparison operators — go.dev/ref/spec#Comparison_operators
- Integer overflow (two's complement) — go.dev/ref/spec#Integer_overflow
strings.Builder— pkg.go.dev/strings#Buildermath/bits— pkg.go.dev/math/bits