Variables

Up until now we have only seen programs that use literal values (numbers, strings, etc.) but such programs aren't particularly useful. To make truly useful programs we need to learn two new concepts: variables and control flow statements. This chapter will explore variables in more detail.

A variable is a storage location, with a specific type and an associated name. Let's change the program we wrote in chapter 2 so that it uses a variable:

package main

import "fmt"

func main() {
  var x string = "Hello World"
  fmt.Println(x)
}

Notice that the string literal from the original program still appears in this program, but rather than send it directly to the Println function we assign it to a variable instead. Variables in Go are created by first using the var keyword, then specifying the variable name (x), the type (string) and finally assigning a value to the variable (Hello World). The last step is optional so an alternative way of writing the program would be like this:

package main

import "fmt"

func main() {
  var x string
  x = "Hello World"
  fmt.Println(x)
}

Variables in Go are similar to variables in algebra but there are some subtle differences:

First when we see the = symbol we have a tendency to read that as “x equals the string Hello World”. There's nothing wrong with reading our program that way, but it's better to read it as “x takes the string Hello World” or “x is assigned the string Hello World”. This distinction is important because (as their name would suggest) variables can change their value throughout the lifetime of a program. Try running the following:

package main

import "fmt"

func main() {
  var x string
  x = "first"
  fmt.Println(x)
  x = "second"
  fmt.Println(x)
}

In fact you can even do this:

var x string
x = "first "
fmt.Println(x)
x = x + "second"
fmt.Println(x)

This program would be nonsense if you read it like an algebraic theorem. But it makes sense if you are careful to read the program as a list of commands. When we see x = x + "second" we should read it as “assign the concatenation of the value of the variable x and the string literal second to the variable x.” The right side of the = is done first and the result is then assigned to the left side of the =.

The x = x + y form is so common in programming that Go has a special assignment statement: +=. We could have written x = x + "second" as x += "second" and it would have done the same thing. (Other operators can be used the same way)

Another difference between Go and algebra is that we use a different symbol for equality: ==. (Two equal signs next to each other) == is an operator like + and it returns a boolean. For example:

var x string = "hello"
var y string = "world"
fmt.Println(x == y)

This program should print false because hello is not the same as world. On the other hand:

var x string = "hello"
var y string = "hello"
fmt.Println(x == y)

This will print true because the two strings are the same.

Since creating a new variable with a starting value is so common Go also supports a shorter statement:

x := "Hello World"

Notice the : before the = and that no type was specified. The type is not necessary because the Go compiler is able to infer the type based on the literal value you assign the variable. (Since you are assigning a string literal, x is given the type string) The compiler can also do inference with the var statement:

var x = "Hello World"

The same thing works for other types:

x := 5
fmt.Println(x)

Generally you should use this shorter form whenever possible.

How to Name a Variable

Naming a variable properly is an important part of software development. Names must start with a letter and may contain letters, numbers or the _ (underscore) symbol. The Go compiler doesn't care what you name a variable so the name is meant for your (and others) benefit. Pick names which clearly describe the variable's purpose. Suppose we had the following:

x := "Max"
fmt.Println("My dog's name is", x)

In this case x is not a very good name for a variable. A better name would be:

name := "Max"
fmt.Println("My dog's name is", name)

or even:

dogsName := "Max"
fmt.Println("My dog's name is", dogsName)

In this last case we use a special way to represent multiple words in a variable name known as lower camel case (also know as mixed case, bumpy caps, camel back or hump back). The first letter of the first word is lowercase, the first letter of the subsequent words is uppercase and all the other letters are lowercase.

Scope

Going back to the program we saw at the beginning of the chapter:

package main

import "fmt"

func main() {
  var x string = "Hello World"
  fmt.Println(x)
}

Another way of writing this program would be like this:

package main

import "fmt"

var x string = "Hello World"

func main() {
  fmt.Println(x)
}

Notice that we moved the variable outside of the main function. This means that other functions can access this variable:

var x string = "Hello World"

func main() {
  fmt.Println(x)
}

func f() {
  fmt.Println(x)
}

The f function now has access to the x variable. Now suppose that we wrote this instead:

func main() {
  var x string = "Hello World"
  fmt.Println(x)
}

func f() {
  fmt.Println(x)
}

If you run this program you should see an error:

.\main.go:11: undefined: x

The compiler is telling you that the x variable inside of the f function doesn't exist. It only exists inside of the main function. The range of places where you are allowed to use x is called the scope of the variable. According to the language specification “Go is lexically scoped using blocks”. Basically this means that the variable exists within the nearest curly braces { } (a block) including any nested curly braces (blocks), but not outside of them. Scope can be a little confusing at first; as we see more Go examples it should become more clear.

Constants

Go also has support for constants. Constants are basically variables whose values cannot be changed later. They are created in the same way you create variables but instead of using the var keyword we use the const keyword:

package main

import "fmt"

func main() {
  const x string = "Hello World"
  fmt.Println(x)
}

This:

const x string = "Hello World"
x = "Some other string"

Results in a compile-time error:

.\main.go:7: cannot assign to x

Constants are a good way to reuse common values in a program without writing them out each time. For example Pi in the math package is defined as a constant.

Defining Multiple Variables

Go also has another shorthand when you need to define multiple variables:

var (
  a = 5
  b = 10
  c = 15
)

Use the keyword var (or const) followed by parentheses with each variable on its own line.

An Example Program

Here's an example program which takes in a number entered by the user and doubles it:

package main

import "fmt"

func main() {
  fmt.Print("Enter a number: ")
  var input float64
  fmt.Scanf("%f", &input)

  output := input * 2

  fmt.Println(output)
}

We use another function from the fmt package to read the user input (Scanf). &input will be explained in a later chapter, for now all we need to know is that Scanf fills input with the number we enter.

Problems

← Previous Index Next →