CodeRigor

LESSON

Name values with variables

Create variables for whole numbers, decimals and text, calculate with them, convert between number types and print values inside lines of text.

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.

Go
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 as 3, 0 or -12.
  • float64: a number with a decimal point, such as 2.5 or 0.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:

Go
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).

Go
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:

Text
9
14
3
1
3.5

Look 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.

Go
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.

What each name refers to, line by line
start / 6 ⇄ code
total was given the value 12 when line 8 ran. Changing quantity later does not go back and recalculate it.
What each name refers to, line by line
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:

Go
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.

How one assignment statement runs
start / 3
Go finishes the right-hand side before it touches the name on the left. That is why count = count + 1 makes sense: the old value is used first, then the name moves to the new value.
How one assignment statement runs
Go finishes the right-hand side before it touches the name on the left. That is why 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.

Go
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:

Go
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:

  • %d for an int
  • %s for a string
  • %f for a float64, and %.2f for a float64 shown with exactly two digits after the decimal point
  • %v for any value, shown in Go's usual way
Go
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:

Text
3 x notebook
Total: 7.50

Two 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.

Go
package main

import "fmt"

func main() {
    name := "Ada"
    age := 36
    fmt.Println("Hello,", name)
}
Text
# command-line-arguments
./main.go:7:5: declared and not used: age

Line 7 creates age and nothing reads it. Use the variable, or delete the line.

Mixing types. This is the receipt program without the conversion:

Go
package main

import "fmt"

func main() {
    price := 2.50
    quantity := 3
    fmt.Println(price * quantity)
}
Text
# 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.

Go
package main

import "fmt"

func main() {
    total := 0
    total := total + 5
    fmt.Println(total)
}
Text
# 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.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Starts at 'Variables & Constants in Go' (22:02) and runs on through 'Formatted Output - printf' and 'Data Types in Go' (to 45:18): creating variables, printing them with Printf and the int, float64 and string types.

Starts at the 'Variables' chapter (35:48): the var and := forms, naming and converting between types. It goes into more detail than this lesson; the following 'Primitives' chapter covers the number types in depth and can wait.