AlgoMaster Logo

Operators

Last Updated: May 22, 2026

Medium Priority
6 min read

Operators are the symbols that combine values into expressions: adding prices, comparing stock counts, toggling permission flags, building cart totals. Go's operator set is small and predictable, but a few details to be aware of: integer division truncates decimals and i++ cannot be used inside another expression. This lesson covers every operator you'll use day to day.

Arithmetic Operators

Go has the five arithmetic operators you'd expect: +, -, *, /, and % (remainder). They work on numeric types like int, float64, and friends.

Two things to call out here. First, Go does not auto-convert between numeric types, so multiplying a float64 by an int requires an explicit float64(quantity). Second, % (the remainder operator) works only on integers. Try it on a float64 and the compiler complains.

The Integer Division Gotcha

When both operands are integers, / does integer division and throws away the fractional part. This is easy to overlook.

5 / 2 gives 2, not 2.5. There's no rounding, no error, just truncation toward zero. If you wanted a decimal result, you'd need at least one operand to be a float:

The % operator is the partner to integer division. It returns whatever's left after dividing, which is why it's perfect for "how many leftover items don't fit evenly?" or "is this number even?" checks.

Comparison Operators

Comparison operators return a bool. Go has the six you'd expect: ==, !=, <, <=, >, >=.

Two rules govern comparisons in Go:

  1. Both sides must be the same type. You can't compare an int to a float64 without converting one of them. The compiler rejects 5 == 5.0 with mismatched types int and float64.
  2. The types must be comparable. Numbers, strings, booleans, and pointers are comparable. Slices and maps are not (you can only compare them to nil). Structs are comparable if all their fields are.

For strings, == checks character-by-character equality, and <, >, and friends compare lexicographically (byte by byte, treating each byte as its numeric value).

"books" is less than "boots" because at the third character, 'o' is greater than 'o'... wait, those are equal. Look at the fourth: 'k' (107) versus 't' (116). 'k' is smaller, so "books" sorts first. This is how sort.Strings orders things by default.

Logical Operators

Three logical operators: && (AND), || (OR), ! (NOT). They work only on bool values.

Short-Circuit Evaluation

Go short-circuits && and ||. With a && b, if a is false, Go never evaluates b. With a || b, if a is true, Go never evaluates b. This isn't just a speedup, it's a tool you actively use to guard against nil checks and division by zero.

If Go evaluated both sides, the first if would divide by zero. Short-circuit evaluation is what makes patterns like if user != nil && user.IsActive() safe.

Bitwise Operators

Bitwise operators treat integers as sequences of bits and operate on each bit position. They're less common in everyday business logic, but you'll see them in permission flags, feature toggles, packed configuration values, and compact storage.

OperatorNameWhat It Does
&ANDBit is 1 only if both operands have 1 at that position
|ORBit is 1 if either operand has 1 at that position
^XORBit is 1 if exactly one operand has 1 at that position
&^AND NOT (bit clear)Bit is 1 if left has 1 and right has 0
<<Left shiftMove bits left, fill right with 0 (multiply by 2 per shift)
>>Right shiftMove bits right, drop low bits (divide by 2 per shift)

The &^ operator is unusual: most languages don't have it. a &^ b clears every bit in a that's set in b. Think of it as "AND with the complement of b".

Permission Flags Example

A classic use case is packing multiple yes/no flags into one integer. Each bit position represents a permission.

The pattern is:

  • flags | X adds permission X.
  • flags &^ X removes permission X.
  • flags & X != 0 checks if X is set.
  • flags ^ X toggles X.

Shift Operators

<< and >> shift bits left or right. Each left shift doubles the value, each right shift halves it (for non-negative integers).

Assignment Operators

The basic assignment is =. Go also has compound assignment operators that combine an operation with assignment.

OperatorEquivalent ToExample Use
+=x = x + yAdding an item's price to a running cart total
-=x = x - yDecreasing stock when an order ships
*=x = x * yApplying a multiplier to a price
/=x = x / yScaling a value down
%=x = x % yReducing to a remainder
&=x = x & yMasking off bits
|=x = x | ySetting bits
^=x = x ^ yToggling bits
<<=x = x << yShifting left
>>=x = x >> yShifting right

The most common one in beginner code is +=, especially in totals.

Compound operators are not just shorter, they often read more naturally. total += price says "add this price to the total" in a way that total = total + price does not.

One thing to remember: +=, -=, and the rest are statements, not expressions. You can't write result := (x += 5) like in some other languages.

Increment and Decrement

Go has i++ and i--, but they behave differently than in most languages.

So far, so normal. Here's where Go differs:

  1. `i++` and `i--` are statements, not expressions. You can't use them inside another expression. This is illegal:
  1. There's no prefix form. Go has i++ (postfix), not ++i. Writing ++i is a syntax error.

Both rules exist to keep code unambiguous. In languages with prefix and postfix forms, expressions like a[i++] = b[++j] are easy to write and hard to read. Go sidesteps the problem entirely by making increments standalone statements.

If you wanted to use the new value in an expression, you increment first, then use it:

Operator Precedence

When an expression has multiple operators, Go evaluates them in a fixed order. Go has only 5 precedence levels for binary operators, which is fewer than most languages and easier to remember.

LevelOperatorsType
5 (highest)* / % << >> & &^Multiplicative
4+ - | ^Additive
3== != < <= > >=Comparison
2&&Logical AND
1 (lowest)||Logical OR

Unary operators (!, -x, *p, &x, ^x) bind tighter than any binary operator. So !a && b means (!a) && b, not !(a && b).

A few worked examples:

The third example has a non-obvious evaluation order. Reading left to right makes you think (true || false) && false is false. But && binds tighter than ||, so it's actually true || (false && false), which is true || false, which is true.

When in doubt, add parentheses. They're free and they make intent explicit:

String Concatenation with +

Go uses + to concatenate strings. The two operands have to be strings; you can't + a string and an integer.

For a handful of concatenations, + is fine. But there's a trap when you do it in a loop.

So this is fine:

But this is not:

Pointer and Channel Operators (Brief Mention)

Go has a few more operator-like symbols you'll encounter:

  • &x takes the address of x (produces a pointer to it).
  • *p dereferences pointer p (gives the value it points to).
  • ch <- value sends value to channel ch.
  • value := <-ch receives a value from channel ch.

& and * are unary in this context (operating on one value), not the bitwise & or arithmetic * you saw above. Go reuses the symbols, and the compiler tells them apart by where they appear.

Putting It Together

Here's an example that uses most of what this lesson covered: arithmetic for a cart total, compound assignment, comparison for filters, logical operators for eligibility, and bitwise for user permissions.

Every operator here is doing something the others can't easily replace. The arithmetic builds the total, += keeps the loop readable, comparison drives the coupon check, bitwise tracks permissions compactly, and integer division plus % handles pagination.