Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Go  Module 2 – Basics: values, types and control flow

Operators, precedence and bit manipulation

Go's arithmetic, comparison, logical and bitwise operators, its five precedence levels, why it has no ?: or x++ inside expressions, and flags and masks.

  • Beginner
  • 10 minutes
  • Examples run with Go 1.27.1 and Python 3.14.8
  • By MySmartCoPilot
Free core, Pro depth: 4 of 10 minutes free
Free: Operators need one type, and the logical ones stop early · Five precedence levels decide where the parentheses go · Go has no conditional operator, and increments are statements · Bitwise operators work on the bits of integers. With a pass: 2 in-depth parts and 3 interview answers, about 6 minutes.

What you will learn

  • Use arithmetic, comparison, logical and bitwise operators correctly
  • Apply Go's five precedence levels without extra parentheses
  • Explain why Go has no ?: operator and why ++ is a statement
  • Use &^, shifts and masks for flags and compact encodings

Before you start

1 + 2<<1 is 5 in Go, not 6: a shift binds as tightly as a multiplication, so it runs before the addition. Go has only five operator precedence: The rule that decides which operator of an expression is grouped first. Go has five levels for binary operators, from * / % << >> & &^ down to ||, and operators on one level group from left to right. levels for its binary operators, few enough to know by heart, and with them most expressions need no parentheses.

You will use Go’s operators, group an expression by precedence, see why Go has no ?: and no x++ inside an expression, and read the bitwise operators on real bits.

Operators need one type, and the logical ones stop early

Arithmetic takes two operands of the same type and gives a result of that type, so 499 / 3 between ints is 166 and % gives the remainder, 1. + also joins strings. Comparisons give a bool, and strings compare byte by byte, which puts “Zoo” before “apple”: ‘Z’ is the byte 90 and ‘a’ the byte 97. The logical operators && and || use short-circuit evaluation: The way && and || work: the right operand is evaluated only when the left one does not decide the result, so a check on the left can protect the expression on the right.: they evaluate their right side only when the left side does not settle the answer:

operators_basics.go: arithmetic, comparisons and a guard Go · operators_basics.go
// operators_basics.go: arithmetic, comparison and logical operators.
package main

import "fmt"

func main() {
	price, qty := 499, 3
	fmt.Println(price*qty, price/qty, price%qty, -price)
	fmt.Println("total" + " " + "due") // + also joins strings

	fmt.Println(price > 400, price == 499, "apple" < "banana", "Zoo" < "apple")

	codes := []string{"B2", "S4"}
	i := 5
	ok := i < len(codes) && codes[i] == "B2" // && stops before codes[5] could run
	fmt.Println("in range and B2:", ok)
}

Output

1497 166 1 -499
total due
true true true true
in range and B2: false

Recorded with Go 1.27.1 on macOS 26 arm64. To run it yourself: go run operators_basics.go

i < len(codes) is false, so codes[i] never runs, and the program does not panic on index 5. Put the cheap or protecting test on the left of &&: a length check before an index, a nil check before a field.

Checkpoint

Check: Operators of one type, and short-circuit logic

  1. Question 1 of 2 Between two ints, what do 499 / 3 and 499 % 3 give?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: 166 and 1

    An arithmetic operator gives a result of its operands' type, so ints divide into an int.

  2. Question 2 of 2 The guard from operators_basics.go, with its two sides swapped. What happens?

    Read the code, then choose one answer.

    codes := []string{"B2", "S4"}
    i := 5
    fmt.Println(codes[i] == "B2" && i < len(codes))
    Show the answer: Question 2 of 2

    Answer: It panics: index out of range [5] with length 2

    && and || evaluate left to right and stop as soon as the answer is known, so the protecting test goes on the left.

Five precedence levels decide where the parentheses go

Every binary operator belongs to one of five levels, and the higher level is grouped first:

Level Operators Grouped
5 * / % << >> & &^ first
4 + - | ^ second
3 == != < <= > >= third
2 && fourth
1 || last

Unary operators, such as -x, !ok and ^x, bind more tightly than any of them, and operators of one level group from left to right, so 10-4-3 is 3. The shifts and & sit with multiplication, and | with addition:

precedence.go: the same operators on five levels Go · precedence.go
// precedence.go: the same operators, grouped by Go's five levels.
package main

import "fmt"

func main() {
	a, b := 1, 2
	fmt.Println(a + b<<1)     // 5: << binds like *, so it runs before +
	fmt.Println((a + b) << 1) // 6

	flags, mask := 6, 4
	fmt.Println(flags&mask == 0) // false: & runs before ==

	fmt.Println(10-4-3, 100/10*2) // one level: left to right

	n, ok := 7, true
	fmt.Println(n+2<<1 > 9 && ok) // ((n + (2<<1)) > 9) && ok
}

Output

5
6
false
3 20
true

Recorded with Go 1.27.1 on macOS 26 arm64. To run it yourself: go run precedence.go

Step through the last line, which needs no parentheses at all:

Interactive · stage by stage How Go groups n+2<<1 > 9 && ok Step through the expression from precedence.go, strongest level first, with n = 7 and ok true.
How Go groups n+2<<1 > 9 && ok, step 4 of 4. Showing 2<<1 is 4, n + 4 is 11, 11 > 9 is true, true && ok is true. In focus: true && ok is true.2<<1 is 4level 5, with * and &n + 4 is 11level 4, with - and |11 > 9 is truelevel 3: comparisonstrue && ok is truelevel 2: &&

The drawing shows the whole scene; its 4 steps are listed below.

Every step as text
  1. The strongest level. Go first groups the operators of level 5. The shift 2<<1 belongs there, beside * and &, so it is worked out first and gives 4.
  2. Then addition. Level 4 holds + and -, and | and ^ as well. n + 4 is 7 + 4, which is 11. A reader who added first would have shifted 9 instead and got 18.
  3. Then the comparison. Comparisons are level 3, so 11 > 9 compares the finished sum and gives true. No comparison ever needs parentheses around the arithmetic on either side.
  4. Logic comes last. is level 2 and || level 1, so they join finished comparisons. true && ok is true, which the program printed.

flags&mask == 0 is read as (flags & mask) == 0, because & is on level 5 and == on level 3, so the bit test needs no parentheses. Where a reader could still hesitate, add them anyway: they cost nothing.

Checkpoint

Check: The five precedence levels

  1. Question 1 of 2 With a := 3, what is a*2 + 1<<2?

    Type a number.

    A hint

    * and << are both on level 5, above +.

    Show the answer: Question 1 of 2

    Answer: 10

    a*2 is 6 and 1<<2 is 4, both level 5, so they are grouped first; then 6 + 4 is 10. (6 + 1) << 2 would be 28.

  2. Question 2 of 2 How does Go group x&1 == 0 || y > 2?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: ((x & 1) == 0) || (y > 2)

    Go's levels put bit operators with arithmetic, above comparisons, so a bit test reads naturally without parentheses.

Go has no conditional operator, and increments are statements

Two familiar operators are missing on purpose. There is no conditional operator ?::

ternary.go: a ?: in Go Go · ternary.go
// ternary.go: Go has no ?: operator.
package main

import "fmt"

func main() {
	paid := true
	label := paid ? "paid" : "due"
	fmt.Println(label)
}

Output (exit status 1)

Printed as an error (standard error)

# command-line-arguments
./ternary.go:8:16: invalid character U+003F '?'
./ternary.go:8:18: syntax error: unexpected literal "paid" at end of statement

Recorded with Go 1.27.1 on macOS 26 arm64. To run it yourself: go run ternary.go

And ++ and -- are statements, not expressions, so they cannot give a value:

plusplus.go: the value of count++ Go · plusplus.go
// plusplus.go: ++ is a statement, so it cannot give a value.
package main

import "fmt"

func main() {
	count := 1
	next := count++
	fmt.Println(next)
}

Output (exit status 1)

Printed as an error (standard error)

# command-line-arguments
./plusplus.go:8:15: syntax error: unexpected ++ at end of statement

Recorded with Go 1.27.1 on macOS 26 arm64. To run it yourself: go run plusplus.go

Go’s FAQ gives the reasons. The designers had seen ?: used to build expressions that were hard to read, and an if-else is clearer; making ++ a statement removes the questions about evaluation order that f(i++) raises. Write label := "due" and then if paid { label = "paid" }, and write count++ on a line of its own.

Assignment is a statement as well, so it cannot stand where a value is needed. That makes the classic slip of = for == in a condition a compile error instead of a bug:

assign_if.go: = where == was meant Go · assign_if.go
// assign_if.go: an assignment where a condition belongs.
package main

import "fmt"

func main() {
	x := 3
	if x = 5 {
		fmt.Println(x)
	}
}

Output (exit status 1)

Printed as an error (standard error)

# command-line-arguments
./assign_if.go:8:7: syntax error: cannot use assignment x = 5 as value

Recorded with Go 1.27.1 on macOS 26 arm64. To run it yourself: go run assign_if.go

The compiler stopped with cannot use assignment x = 5 as value, before the program could run.

Checkpoint

Check: No conditional operator, and ++ as a statement

  1. Question 1 of 2 Which code gives fee the value 50 when express is true, and 0 otherwise?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: fee := 0, then if express { fee = 50 }

    A conditional value is an if statement: assign the default, then assign the other value inside the if.

  2. Question 2 of 2 Which of these compiles in Go?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: i++ on a line of its own

    ++ and -- are statements in postfix form only, which removes every question about when the increment happens.

Bitwise operators work on the bits of integers

Bit manipulation means working on the single bits of an integer, which is how flags, masks and compact encodings are built. Go has six bitwise operators for it, shown here on 12 and 10, which are 1100 and 1010 in binary:

bitwise.go: the bit operators on 12 and 10 Go · bitwise.go
// bitwise.go: the bit operators on 12 (1100) and 10 (1010).
package main

import "fmt"

func main() {
	x, y := 12, 10
	fmt.Printf("x      %04b = %d\n", x, x)
	fmt.Printf("y      %04b = %d\n", y, y)
	fmt.Printf("x & y  %04b = %d\n", x&y, x&y)
	fmt.Printf("x | y  %04b = %d\n", x|y, x|y)
	fmt.Printf("x ^ y  %04b = %d\n", x^y, x^y)
	fmt.Printf("x &^ y %04b = %d\n", x&^y, x&^y)
	fmt.Printf("x << 1 %b = %d\n", x<<1, x<<1)
	fmt.Printf("x >> 2 %04b = %d\n", x>>2, x>>2)

	var u uint8 = 12
	fmt.Printf("^u     %08b = %d, for a uint8\n", ^u, ^u)
	fmt.Println("^x =", ^x, "for an int, which is -x - 1")
}

Output

x      1100 = 12
y      1010 = 10
x & y  1000 = 8
x | y  1110 = 14
x ^ y  0110 = 6
x &^ y 0100 = 4
x << 1 11000 = 24
x >> 2 0011 = 3
^u     11110011 = 243, for a uint8
^x = -13 for an int, which is -x - 1

Recorded with Go 1.27.1 on macOS 26 arm64. To run it yourself: go run bitwise.go

Operator Name Each bit of the result 12 and 10
& AND set where both are set 8, 1000
| OR set where either is set 14, 1110
^ XOR set where exactly one is set 6, 0110
&^ AND NOT set in the left, cleared where the right is set 4, 0100
<< >> shifts moved left or right by the count 24 and 3

^ has a second job: in front of one value it flips every bit, so ^12 is 243 for a uint8 and -13 for an int. Bit manipulation needs integer operands, and it reads best with %b and %08b in a print. &^ clears bits, mask: A value whose set bits pick out which bits of another value an operation keeps, clears or tests. keep the bits you name, shifts move them, and math/bits counts them.

Checkpoint

Check: The bitwise operators

  1. Question 1 of 2 What are 6 & 3 and 6 | 3?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: 2 and 7

    & keeps the bits set in both, | the bits set in either, as the table of bitwise.go shows for 12 and 10.

  2. Question 2 of 2 What are 6 ^ 3, and ^u for a uint8 u that holds 0?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: 5 and 255

    ^ is XOR between two values and bitwise NOT in front of one, and the NOT of an unsigned 0 is its largest value.

Flags, masks and shifts: set, clear, toggle and test, reproduced Pro: opens with a Pro, Premium or Ultimate pass

Four expressions cover nearly everything done with flags: set with |, clear with &^, toggle with ^ and test with &. Here they run on real file permissions, and then three colour channels are packed into one number and taken out again.

In this part:

  • Setting, clearing, toggling and testing permission bits
  • Why AND NOT is the operator for clearing bits
  • Packing three channels into a uint32
  • Shifts at the edges: rounding down, and a negative count

1 diagram · 7 runnable examples (Go, Python) · about 6 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Comparisons and math/bits, measured Pro: opens with a Pro, Premium or Ultimate pass

== works on more than numbers: structs compare field by field and arrays element by element, while slices, maps and functions compare only with nil. math/bits answers the questions that loops over bits used to answer: how many bits are set, where the first one is, and whether a number is a power of two.

In this part:

  • What equality compares, field by field
  • Counting and finding bits with math/bits
  • Flags, a struct of bools or a map: choosing with sizes

4 runnable examples (Go) · about 5 minutes

Opening this part with your pass…Pro part. It opens with the same pass as the part above.

Practise

Practise on operators, precedence, the missing ?: and the bitwise operators. Your shakiest idea is asked about first, and the feedback on each choice says why it is right or where it goes wrong:

Practice that adapts to you

Practise this lesson

11 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 11 Is "B2" < "B10" true in Go?

    Choose one answer.

    Show the answer: Question 1 of 11

    Answer: No, because strings compare byte by byte and '2' comes after '1'

    For a numeric order of codes such as B2 and B10, compare their numbers, not the strings.

  2. Question 2 of 11 What does this print?

    Read the code, then choose one answer.

    func check(name string, v bool) bool {
        fmt.Println("checked", name)
        return v
    }
    
    fmt.Println(check("a", false) && check("b", true))
    Show the answer: Question 2 of 11

    Answer: checked a, then false

    Short-circuiting skips the right side when the left decides, so side effects on the right may not happen.

  3. Question 3 of 11 What happens here?

    Read the code, then choose one answer.

    var n int = 3
    var m int64 = 3
    fmt.Println(n == m)
    Show the answer: Question 3 of 11

    Answer: It does not compile: mismatched types int and int64

    Compare int64(n) == m, the same conversion that arithmetic between the two types needs.

  4. Question 4 of 11 How many precedence levels do Go's binary operators have?

    Choose one answer.

    Show the answer: Question 4 of 11

    Answer: 5

    Five levels, strongest first: * / % << >> & &^, then + - | ^, then comparisons, then &&, then ||.

  5. Question 5 of 11 What is 100 / 10 * 2 in Go?

    Type a number.

    Show the answer: Question 5 of 11

    Answer: 20

    / and * share a level, so they group from left to right: (100 / 10) * 2 is 20, not 100 / 20, as precedence.go printed.

  6. Question 6 of 11 What does this print?

    Read the code, then choose one answer.

    a, b, c := true, false, false
    fmt.Println(a || b && c)
    Show the answer: Question 6 of 11

    Answer: true

    && is level 2 and || level 1, so a || b && c groups like a + b * c does.

  7. Question 7 of 11 What is i after i := 4, then i++, then i++?

    Type a number.

    Show the answer: Question 7 of 11

    Answer: 6

    Each ++ statement adds 1 to i, so 4 becomes 6.

  8. Question 8 of 11 Python's status = "adult" if age >= 18 else "minor" sets status. Which Go code does the same?

    Choose one answer.

    Show the answer: Question 8 of 11

    Answer: status := "minor", then if age >= 18 { status = "adult" }

    Go's FAQ argues the if-else form is clearer, and it is the only form Go has.

  9. Question 9 of 11 What is 13 &^ 6?

    Choose one answer.

    Show the answer: Question 9 of 11

    Answer: 9

    x &^ y keeps the bits of x that are not set in y, which makes it the operator for clearing flags.

  10. Question 10 of 11 What is 3 << 4?

    Type a number.

    Show the answer: Question 10 of 11

    Answer: 48

    Shifting left by 4 multiplies by 2 to the power 4, so 3 × 16 is 48, binary 110000.

  11. Question 11 of 11 x := 5, an int. What is ^x?

    Choose one answer.

    Show the answer: Question 11 of 11

    Answer: -6

    The result of ^ depends on the type: all 64 bits flip for an int, and in two's complement that is -x - 1.

Chmod Calculator Turn rwx choices into octal permission bits, and back, to check your masks.

Interview questions

Warm-up (fresher): How do you write a conditional value in Go, which has no ?: operator?

With an if. Give the variable its default first, then change it when the condition holds: label := "due", then if paid { label = "paid" }. When both branches compute something, declare the variable with var and assign it in an if-else. For a value used in many places, a small function returns it.

Three longer questions of the module bank build on this lesson:

  1. Mid to senior

    You port a checksum routine from C to Go line for line, and its results change. One line is crc = crc << 4 + x & 0xF. Which operators group differently in the two languages, and how do you port bit-level code safely?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Fresher to mid

    A permissions field is a uint8 of flags. Write the expressions that set, clear, toggle and test one flag, and explain why flags & ^1 does not compile while flags &^ 1 does.

    Model answer, Pro. First step and follow-ups

  3. Fresher to mid

    A function packs colours with uint32(r<<16 | g<<8 | b), where r, g and b are uint8 values, and every packed colour comes out as just its blue part. Why, and how do you write and test the packing so the bug cannot return?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • Arithmetic needs operands of one type, comparisons give a bool, and && and || skip their right side when the left decides.
  • Five precedence levels group binary operators: * and the shifts and & first, then + and |, then comparisons, then &&, then ||.
  • Go has no ?:, so a conditional value is an if, and ++ is a statement on a line of its own.
  • The bitwise operators &, |, ^, &^, << and >> work on the bits of integers, and ^x flips every bit.

Terms in this lesson

mask
A value whose set bits pick out which bits of another value an operation keeps, clears or tests.
operator precedence
The rule that decides which operator of an expression is grouped first. Go has five levels for binary operators, from * / % << >> & &^ down to ||, and operators on one level group from left to right.
short-circuit evaluation
The way && and || work: the right operand is evaluated only when the left one does not decide the result, so a check on the left can protect the expression on the right.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.