A program that only prints fixed text is a sign. To calculate, a program has to remember values and work with them. This lesson shows how.
A variable is a name for a value
A value is a piece of data: a number, or some text. A variable is a name that refers to a value, so that later lines can use it.
package main
import "fmt"
func main() {
price := 4
fmt.Println(price)
}This prints 4. The line price := 4 is a declaration: it creates a variable named price and gives it the value 4. Read := as "is a new name for". The next line prints the value that price refers to. Notice there are no quotation marks: fmt.Println(price) prints the variable's value, while fmt.Println("price") would print the word price.
Three types of value
Every value in Go has a type, which says what kind of data it is and what you can do with it. You need three types to begin:
int: an integer, which is a whole number such as3,0or-12.float64: a number with a decimal point, such as2.5or0.1. The odd name describes how the computer stores such a number; think of it as "decimal number".string: text, written between double quotation marks, such as"notebook".
With :=, Go works out the type from the value on the right: 3 makes an int, 2.5 makes a float64 and "tea" makes a string. Once a variable is created its type never changes. A variable that holds an int will hold an int for the rest of the program.
You can also write the type yourself, with the word var:
package main
import "fmt"
func main() {
var quantity int = 3
var price float64 = 2.5
var item string = "notebook"
fmt.Println(item, quantity, price)
}This prints notebook 3 2.5. var quantity int = 3 and quantity := 3 mean the same thing. Inside main, Go programmers nearly always use the short := form. The var form is the only one allowed outside main, and you will see it there in this lesson's build.
When you give fmt.Println several arguments separated by commas, it prints them all on one line with a space between each.
Arithmetic
An expression is anything Go can work out to a single value, such as price * 3. The arithmetic signs are + (add), - (subtract), * (multiply), / (divide) and % (the remainder after dividing whole numbers).
package main
import "fmt"
func main() {
fmt.Println(7 + 2)
fmt.Println(7 * 2)
fmt.Println(7 / 2)
fmt.Println(7 % 2)
fmt.Println(7.0 / 2)
}This prints:
9
14
3
1
3.5Look at the third and last lines. Dividing two whole numbers gives a whole number: 7 / 2 is 3, and the half is thrown away. 7 % 2 is the 1 left over. As soon as one side is written with a decimal point, as in 7.0 / 2, Go divides decimal numbers and keeps the fraction.
Multiplication and division happen before addition and subtraction, as in school arithmetic: 2 + 3 * 4 is 14. Round brackets change the order: (2 + 3) * 4 is 20.
Changing a variable
:= creates a variable. To give an existing variable a different value, use = without the colon. This is called assignment.
package main
import "fmt"
func main() {
price := 4
quantity := 3
total := price * quantity
fmt.Println(total)
quantity = 5
fmt.Println(total)
}This prints 12 twice. That surprises many people. total := price * quantity did the multiplication once, when that line ran, and stored the answer 12. It did not create a lasting link between total and quantity. Step through the diagram.
total was given the value 12 when line 8 ran. Changing quantity later does not go back and recalculate it.Go always works out the right-hand side first and only then changes the name on the left. That is why this very common statement makes sense:
package main
import "fmt"
func main() {
count := 7
count = count + 1
fmt.Println(count)
}It prints 8. It is not a claim that a number equals itself plus one. It is an instruction: work out count + 1, then make count refer to the result.
count = count + 1 makes sense: the old value is used first, then the name moves to the new value.Adding to a variable is so common that there are two shorter ways to write it. count += 1 means count = count + 1, and count++ means "add one to count". The same pattern works with other signs: total -= 5, price *= 2.
Whole numbers and decimals do not mix on their own
Go will not quietly combine an int with a float64. If price is a float64 and quantity is an int, then price * quantity is refused by the compiler. You have to say what you mean with a conversion: the type's name, followed by the value in round brackets.
package main
import "fmt"
func main() {
price := 2.50
quantity := 3
total := price * float64(quantity)
fmt.Println(total)
}This prints 7.5. float64(quantity) makes a decimal copy of the 3, namely 3.0, so that both sides of * have the same type. The variable quantity itself is still an int.
Choosing names
A name can contain letters, digits and underscores, cannot start with a digit and cannot contain spaces. Capital letters count: total and Total are different names. Go programmers join the words of a longer name by giving each later word a capital letter: unitPrice, itemsLeft. Choose names that say what the value means. unitPrice is better than x.
Putting values into printed text
fmt.Println with several arguments is the quick way, and it always puts a space between them:
package main
import "fmt"
func main() {
name := "Ada"
age := 36
fmt.Println("Name:", name)
fmt.Println(name, "is", age, "years old")
}This prints Name: Ada and then Ada is 36 years old.
For full control there is fmt.Printf (short for "print formatted"). Its first argument is a string with gaps in it, and the remaining arguments fill the gaps in order. Each gap is marked by a verb, which is a % sign followed by a letter saying what kind of value goes there:
%dfor anint%sfor astring%ffor afloat64, and%.2ffor afloat64shown with exactly two digits after the decimal point%vfor any value, shown in Go's usual way
package main
import "fmt"
func main() {
item := "notebook"
quantity := 3
total := 7.5
fmt.Printf("%d x %s\n", quantity, item)
fmt.Printf("Total: %.2f\n", total)
}This prints:
3 x notebook
Total: 7.50Two things to notice. First, fmt.Printf does not end the line for you. The \n at the end of the string means "start a new line here"; leave it out and the next output carries on along the same line. Second, %.2f printed 7.50 where fmt.Println would print 7.5. Use it for money.
You can also join two strings with +: "Hello, " + name is the string Hello, Ada. That works only when both sides are strings.
Three errors you will meet
A variable you never use. Go treats an unused variable as a mistake, because it is usually a sign of a slip.
package main
import "fmt"
func main() {
name := "Ada"
age := 36
fmt.Println("Hello,", name)
}# command-line-arguments
./main.go:7:5: declared and not used: ageLine 7 creates age and nothing reads it. Use the variable, or delete the line.
Mixing types. This is the receipt program without the conversion:
package main
import "fmt"
func main() {
price := 2.50
quantity := 3
fmt.Println(price * quantity)
}# command-line-arguments
./main.go:8:17: invalid operation: price * quantity (mismatched types float64 and int)The message names the expression and the two types that do not match. The fix is the conversion you saw above: price * float64(quantity).
Creating a variable twice. := is for new names only.
package main
import "fmt"
func main() {
total := 0
total := total + 5
fmt.Println(total)
}# command-line-arguments
./main.go:7:11: no new variables on left side of :=total already exists on line 7, so there is nothing new for := to create. To change an existing variable, write = without the colon: total = total + 5.
What you can do now
You can create variables holding whole numbers, decimals and text, calculate with them, change them, convert a whole number to a decimal, and print values inside lines of text with fmt.Println and fmt.Printf. In the exercises you will trace what small programs print, repair two calculations and finish a program that prints a receipt.
Next: read what the user types, so that a program can work with values it was not given in advance.