A program that only stores values isn’t very useful. The whole point is to do something with them — add them, compare them, decide what to do based on their state. This lesson covers the tools Go gives you for that: operators and conditional statements.
Arithmetic operators
The basic math operators work the way you’d expect:
package main
import "fmt"
func main() {
a := 10
b := 3
fmt.Println("Sum: ", a+b)
fmt.Println("Difference:", a-b)
fmt.Println("Product: ", a*b)
fmt.Println("Quotient: ", a/b)
fmt.Println("Remainder: ", a%b)
}
Sum: 13
Difference: 7
Product: 30
Quotient: 3
Remainder: 1
A few things to notice:
- Integer division drops the decimal part.
10 / 3is3, not3.33. If you need a decimal result, usefloat64:float64(a) / float64(b). %is the modulo (remainder) operator.10 % 3 = 1because 10 divided by 3 leaves a remainder of 1. It’s enormously useful — for instance,n % 2 == 0checks ifnis even.
Assignment shortcuts
Adding to a variable is so common Go gives you a shortcut:
// inside main()
score := 0
score += 10 // same as: score = score + 10
score -= 3 // same as: score = score - 3
score *= 2 // same as: score = score * 2
score /= 7 // same as: score = score / 7
fmt.Println(score)
There’s also ++ and -- for the very common case of adding/subtracting 1:
// inside main()
count := 0
count++ // count is now 1
count++ // count is now 2
count-- // count is now 1
fmt.Println(count)
Unlike C or JavaScript,
count++is a statement, not an expression. You can’t writex := count++. Keep it on its own line.
Comparison operators
Comparison operators compare two values and return a bool:
package main
import "fmt"
func main() {
a := 10
b := 20
fmt.Println("a == b:", a == b)
fmt.Println("a != b:", a != b)
fmt.Println("a < b:", a < b)
fmt.Println("a > b:", a > b)
fmt.Println("a <= b:", a <= b)
fmt.Println("a >= b:", a >= b)
}
a == b: false
a != b: true
a < b: true
a > b: false
a <= b: true
a >= b: false
| Operator | Meaning |
|---|---|
== | equal to |
!= | not equal to |
< | less than |
> | greater than |
<= | less than or equal |
>= | greater than or equal |
Comparison works on numbers, strings, and booleans. For strings, it compares lexically — "apple" < "banana" is true.
Logical operators
Combine boolean expressions with these:
// inside main()
isLoggedIn := true
isAdmin := false
fmt.Println(isLoggedIn && isAdmin) // AND: true only if both are true
fmt.Println(isLoggedIn || isAdmin) // OR: true if either is true
fmt.Println(!isLoggedIn) // NOT: flips the value
false
true
false
Go uses short-circuit evaluation: in a && b, if a is already false, Go never even looks at b. Same for ||: if a is true, b is skipped. This matters when b is an expensive function call or could crash if a was false.
The if statement
if is how you make decisions:
package main
import "fmt"
func main() {
age := 18
if age >= 18 {
fmt.Println("You can vote.")
}
}
You can vote.
Notice there are no parentheses around the condition — that’s the Go style. The braces { }, however, are required, even for a single-line block. (This is one of Go’s safety rules — it eliminates a whole category of “I forgot the braces” bugs.)
else and else if
// inside main()
score := 75
if score >= 90 {
fmt.Println("Grade: A")
} else if score >= 80 {
fmt.Println("Grade: B")
} else if score >= 70 {
fmt.Println("Grade: C")
} else {
fmt.Println("Grade: F")
}
Grade: C
Conditions are checked top to bottom; the first one that matches runs and the rest are skipped.
if with a short statement
Go has a powerful shortcut: you can declare a variable inside an if, and that variable is only visible inside the if/else blocks:
// inside main()
if remainder := 10 % 3; remainder == 0 {
fmt.Println("Divisible")
} else {
fmt.Println("Not divisible. Remainder:", remainder)
}
// remainder is no longer accessible here
Not divisible. Remainder: 1
This pattern is everywhere in Go — especially when checking errors, which we’ll cover later.
The switch statement
When you’d write a chain of if/else if with the same variable, switch is cleaner:
package main
import "fmt"
func main() {
day := "Tuesday"
switch day {
case "Monday":
fmt.Println("Start of the week")
case "Tuesday", "Wednesday", "Thursday":
fmt.Println("Mid-week")
case "Friday":
fmt.Println("Almost weekend")
case "Saturday", "Sunday":
fmt.Println("Weekend!")
default:
fmt.Println("Unknown day")
}
}
Mid-week
A few things to notice:
- Each
casecan match multiple values separated by commas - Once a case matches, only its block runs — Go doesn’t “fall through” into the next case automatically (a common gotcha in C and Java). No need for
break. defaultruns if no case matches; it’s optional
switch without an expression
You can also use switch as a cleaner alternative to long if/else if chains:
// inside main()
score := 75
switch {
case score >= 90:
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
default:
fmt.Println("F")
}
This pattern is very Go-flavored — many developers prefer it over if/else if chains because it’s easier to scan visually.
What’s next
You can now make decisions in your programs. The remaining piece of basic control flow is repetition — running the same code many times. That’s what loops are for, and that’s what’s next.