What a mathematical expression is
An expression is a piece of code that Go can evaluate to a single value. 3 - 4 + 6 is an expression, and so is 2 * price + bag. You can chain as many operators as you like in one line, mix numbers with variables, and pass the whole thing straight to fmt.Println, which prints the final value.
Go has the usual arithmetic operators: +, -, *, / and %. When several of them appear together, two rules decide the result: multiplication, division and remainder run before addition and subtraction, and operators of the same rank run from left to right.
Syntax and examples
With plain numbers
fmt.Println(3 - 4 + 6) // 5
fmt.Println(5 + 2 - 3) // 4
fmt.Println(2 * 5 + 1) // 11
fmt.Println(4 / 2 * 5) // 10
The first line is read left to right: 3 - 4 is -1, and -1 plus 6 is 5. In the third line the multiplication happens first, so Go computes 10 + 1. In the last line, / and * have the same rank, so the division goes first: 4 / 2 is 2, and 2 times 5 is 10.
With variables
A variable can stand wherever a number can. Go reads its current value and does the same calculation:
num1 := 5
num2 := -1
fmt.Println(2 * num1 * num2) // -10
fmt.Println(num1 + num2 - 3) // 1
fmt.Println(20 / num1 + num2) // 3
fmt.Println(num1 / 5 * num2) // -1
In the third line, 20 / num1 is 4, and adding num2, which is -1, gives 3. In the fourth line, num1 / 5 is 1, and 1 times -1 is -1. Both variables hold whole numbers, so every division here is integer division: any fractional part is dropped, so 7 / 2 gives 3, not 3.5.
The order of evaluation matters
The same numbers can give different answers depending on how you group them. Here are a few variations, with their output:
fmt.Println(7 / 2 * 2) // 6
fmt.Println(7 * 2 / 2) // 7
fmt.Println(2 * 7 / 2) // 7
All three lines use the same operators and the same numbers, but the first one divides 7 by 2 before multiplying, and integer division throws away the 0.5. That is why it prints 6. When an integer division is part of a longer expression, put the multiplication first if you want to keep as much precision as possible, or add parentheses to make your intent clear.
Parentheses are always allowed and change the order: (2 + 3) * 4 is 20, while 2 + 3 * 4 is 14. Precedence has a lesson of its own in this chapter.
The lesson's exercise
The lesson gives two variables, price and bag. They hold the price of one product (93) and of one bag (7). The task has two parts, and each ends with a fmt.Println.
- Andy buys four products and one bag. The total is four times the price of a product, plus the price of the bag. Because
*runs before+, you don't need parentheses:4 * price + bagmultiplies first and then adds. - Mary has 150 dollars and wants two products and one bag. First work out her total,
2 * price + bag. Then subtract the money she already has to see how much more she needs. Since+and-have the same rank, Go evaluates2 * price + bag - 150from left to right: the total is built first, and 150 is subtracted at the end.
price := 93
bag := 7
fmt.Println(4 * price + bag)
fmt.Println(2 * price + bag - 150)
The first line prints 379, because 4 times 93 is 372, and 372 plus 7 is 379. The second prints 43: two products cost 186, adding the bag makes 193, and 193 minus 150 leaves 43 dollars still to find.
Notice that := declares each variable and infers its type from the value, so both are int. If the answer were negative, Mary would already have enough money; this exercise's numbers keep it positive.
Common mistakes and gotchas
- Forgetting that division of integers truncates.
num1 / 5 * num2andnum2 * num1 / 5can differ when the division doesn't come out even. - Assuming left to right everywhere. Go reads
2 + 3 * 4as2 + (3 * 4), not(2 + 3) * 4. Left to right only breaks ties between operators of the same rank. - Mixing integer and decimal variables. If one variable is a
float64and another anint, an expression combining them does not compile (invalid operation: price * n (mismatched types float64 and int)). Convert one of them first, for exampleprice * float64(n). - Missing spaces are fine, but readability matters.
4*price+bagworks the same as the spaced version. A formatter such asgofmtactually removes spaces around higher-ranked operators to make the grouping visible.
Key takeaways
- You can combine as many operators as you want in one expression, with numbers and variables alike.
*,/and%run before+and-; operators of equal rank run from left to right.- With two integers,
/drops the fractional part, so the order of the operations can change the result. - Parentheses force the order you want.