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 / 3 is 3, not 3.33. If you need a decimal result, use float64: float64(a) / float64(b).
  • % is the modulo (remainder) operator. 10 % 3 = 1 because 10 divided by 3 leaves a remainder of 1. It’s enormously useful — for instance, n % 2 == 0 checks if n is 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 write x := 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
OperatorMeaning
==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 case can 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.
  • default runs 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.

Toggle theme (T)