Operators
Operators are the symbols that do work on values: + adds, == compares, && combines conditions. Most of them look like those in C, Java or JavaScript, but Go has a few rules of its own that catch people who come from other languages.
In this lesson you will use arithmetic, assignment, comparison, logical and bitwise operators, and learn Go's precedence rules and the operators Go deliberately leaves out.
Arithmetic operators
| Operator | Meaning | Example (a := 17, b := 5) | Result |
|---|---|---|---|
+ | Add (also joins strings) | a + b | 22 |
- | Subtract | a - b | 12 |
* | Multiply | a * b | 85 |
/ | Divide | a / b | 3 |
% | Remainder | a % b | 2 |
When both sides are integers, / is integer division: the fraction is thrown away, towards zero. The % (remainder) operator works only on integers, and its sign follows the left side.
package main
import "fmt"
func main() {
players := 17
teamSize := 5
fmt.Println("Full teams:", players/teamSize)
fmt.Println("Players left over:", players%teamSize)
loss := -17
fmt.Println(loss/teamSize, loss%teamSize)
distance := 7.0
fmt.Println(distance / 2)
fmt.Println("Ro" + "htak")
}Full teams: 3 Players left over: 2 -3 -2 3.5 Rohtak
Seventeen players make 3 full teams of five with 2 left over. With a negative number the result moves towards zero, so -17 / 5 is -3 and the remainder is -2. With a float64, / keeps the fraction.
Assignment operators and ++
Each arithmetic operator has a short assignment form: x += 5 means x = x + 5. Go also has ++ and --, but they are statements, not expressions. You can write count++ on its own line, but not total = count++ or ++count.
package main
import "fmt"
func main() {
score := 10
score += 5 // 15
score *= 2 // 30
score -= 4 // 26
score /= 3 // 8 (integer division)
score %= 5 // 3
score++ // 4
fmt.Println("Final score:", score)
}Final score: 4
Making ++ a statement removes a whole family of confusing C puzzles such as i = i++ + ++i. In Go, each line does one clear thing.
Comparison and logical operators
Comparison operators (==, !=, <, <=, >, >=) produce a bool. Both sides must have the same type: comparing an int with a float64 variable is a compile error.
Logical operators combine bool values: && (and), || (or) and ! (not).
package main
import "fmt"
func main() {
age := 19
hasVoterID := true
marks := 72
canVote := age >= 18 && hasVoterID
scholarship := marks >= 90 || (marks >= 70 && age < 21)
fmt.Println("Can vote:", canVote)
fmt.Println("Scholarship:", scholarship)
fmt.Println("Cannot vote:", !canVote)
}Can vote: true Scholarship: true Cannot vote: false
&& and || short-circuit: Go stops as soon as the answer is known. In len(names) > 0 && names[0] == "Priya", the second part runs only when the slice is not empty, so it can never crash with an index error. Put the cheap or safe check first.
Bitwise operators
Bitwise operators work on the individual bits of integers. They are common for flags and permissions:
| Operator | Name | Effect |
|---|---|---|
& | AND | Bit is 1 if both bits are 1 |
| | OR | Bit is 1 if either bit is 1 |
^ | XOR | Bit is 1 if the bits differ (as a prefix, ^x flips every bit) |
&^ | AND NOT (bit clear) | Clears the bits that are set on the right |
<<, >> | Shift left, right | Moves bits; 1 << 3 is 8 |
package main
import "fmt"
const (
Read = 1 << iota // 1 (binary 001)
Write // 2 (binary 010)
Delete // 4 (binary 100)
)
func main() {
perm := Read | Write
fmt.Println("perm:", perm)
fmt.Println("can write:", perm&Write != 0)
fmt.Println("can delete:", perm&Delete != 0)
perm &^= Write // take away write access
fmt.Println("after clear:", perm)
fmt.Printf("%03b\n", Read|Delete)
}perm: 3 can write: true can delete: false after clear: 1 101
&^ is unique to Go: perm &^ Write keeps every bit of perm except those set in Write. The %03b verb prints a number in binary, padded to three digits.
Precedence
Go has only five precedence levels for binary operators, from highest to lowest:
*/%<<>>&&^+-|^==!=<<=>>=&&||
Notice that & binds tighter than ==. That is why perm&Write != 0 above means (perm&Write) != 0. In C the opposite is true, which causes real bugs there. Use brackets whenever an expression is not obvious at a glance; gofmt even removes spaces around the tighter operators to hint at the grouping.
What Go leaves out
- No ternary operator. There is no
cond ? a : b. Write a shortif:
status := "Fail"
if marks >= 40 {
status = "Pass"
}- No automatic type mixing.
intplusfloat64must be converted first. - No operator overloading.
+on your own types is not possible; you write methods instead.
Common mistakes
- Expecting
7 / 2to be3.5. Two integers give3. Write7.0 / 2or convert tofloat64. - Writing
x = i++.++is a statement in Go, so this does not compile. - Using
^for powers.2 ^ 3is XOR (which gives 1), not 8. Usemath.Pow(2, 3)or a shift such as1 << 3. - Comparing different types.
count == 2.5wherecountis anintvariable will not compile.
Key points
- Integer
/drops the fraction towards zero;%gives the remainder with the sign of the left side. ++and--are postfix statements, not expressions.&&and||short-circuit, so put safety checks first.- Bitwise operators include Go's own
&^(bit clear);&binds tighter than==. - Go has no ternary operator and never mixes numeric types automatically.
Exercise
A school bus in Lucknow carries 42 students and each van carries 9. Print how many full vans are needed, how many students are left over, and the total number of vans needed (full vans plus one more if anyone is left over). Then print whether a student aged 15 with a bus pass may travel alone, using the rule: age 14 or more AND has a pass.
Show solution
package main
import "fmt"
func main() {
students := 42
perVan := 9
full := students / perVan
left := students % perVan
vans := full
if left > 0 {
vans++
}
fmt.Println("Full vans:", full, "Left over:", left, "Vans needed:", vans)
age := 15
hasPass := true
fmt.Println("May travel alone:", age >= 14 && hasPass)
}Full vans: 4 Left over: 6 Vans needed: 5 May travel alone: true
42 divided by 9 is 4 with remainder 6, so one extra van is needed. A plain if replaces the ternary operator other languages use.
Quick Quiz
1. What does 17 % 5 evaluate to in Go?
17 is 3 fives (15) plus 2, so the remainder is 2.
2. Which line compiles in Go?
++ is a postfix statement and must stand alone on its line.
3. What does 2 ^ 3 give in Go?
^ is bitwise XOR: binary 10 XOR 11 is 01, which is 1.
4. How does Go read flags&Write != 0?
In Go, & has higher precedence than comparison operators.
Learn Go with a mentor
Free lessons get you started. Our Programming & Software Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
