Introduction to Go Variables

GoGoBeginner
Practice Now

Introduction

Why do we need variables in computer programming languages? This is an age-old question. Just as we can remember that the URL for the LabEx is labex.io, computer programs also need to remember some data for their use.

The purpose of variables is to represent a piece of data. In this section, we will explore how variables are used in the Go language.

Knowledge Points:

  • Variable declaration
  • Variable initialization
  • Variable usage
  • Variable lifetime
  • Constants

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("`Go`")) -.-> go/BasicsGroup(["`Basics`"]) go(("`Go`")) -.-> go/FunctionsandControlFlowGroup(["`Functions and Control Flow`"]) go(("`Go`")) -.-> go/DataTypesandStructuresGroup(["`Data Types and Structures`"]) go(("`Go`")) -.-> go/ObjectOrientedProgrammingGroup(["`Object-Oriented Programming`"]) go/BasicsGroup -.-> go/variables("`Variables`") go/BasicsGroup -.-> go/constants("`Constants`") go/FunctionsandControlFlowGroup -.-> go/functions("`Functions`") go/FunctionsandControlFlowGroup -.-> go/closures("`Closures`") go/DataTypesandStructuresGroup -.-> go/strings("`Strings`") go/ObjectOrientedProgrammingGroup -.-> go/struct_embedding("`Struct Embedding`") subgraph Lab Skills go/variables -.-> lab-149065{{"`Introduction to Go Variables`"}} go/constants -.-> lab-149065{{"`Introduction to Go Variables`"}} go/functions -.-> lab-149065{{"`Introduction to Go Variables`"}} go/closures -.-> lab-149065{{"`Introduction to Go Variables`"}} go/strings -.-> lab-149065{{"`Introduction to Go Variables`"}} go/struct_embedding -.-> lab-149065{{"`Introduction to Go Variables`"}} end

What is a variable?

What is a variable? In simple terms, a variable is a container used to store and save a piece of mutable data.

In compiled languages such as Go, the type of a variable is fixed.

What does it mean for a variable type to be fixed?

It means that a variable can only hold one type of data. In other words, the items stored in the variable container are fixed.

If a variable is used to hold fruit, it should only hold fruit. Once the container has held fruit, it cannot be used to hold cookies. This is reflected in the code as a variable cannot be assigned with two different types of data.

Variable Mutability

As the name implies, a variable's value can change, as long as the change does not exceed the range allowed by its type.

For example, the level of the LabEx Cloud Course is a typical variable. It stores the floor number of each student and will increase as the learning time increases.

At the same time, the Go language has the following rules for variables:

  • The name must consist of numbers, letters, and underscores.
  • The variable identifier cannot start with a number.
  • The identifier cannot be a reserved keyword. Check reserved keywords
  • Variable names are case-sensitive, but it is not recommended to use different casing to distinguish between two variables with the same name.

General Declaration Method

In the Go language, the keyword used to declare variables in the general method is var.

The form of declaration is: var identifier type, which means:

var variableName variableType.

What are the common variable types in Go?

Keyword Explanation
int Integer. The most common data type, taught in primary school mathematics.
string String. A string of characters wrapped in double quotes, such as: "hello,world"
bool Boolean. Represents true or false, with two possible values: true or false

Since variable types are not the focus of this section, only the three most common types are listed.

More types will be explained in the following courses.

How do we declare a variable?

Now let's declare an integer variable named a.

var a int

How to remember it? You can silently say in your mind:

Define a variable named `a`, which is of type int.

Unlike many traditional programming languages, the variable type used in Go is placed after the variable name.

This way of declaring variables makes the code easier to read from left to right and avoids the spiral reading logic of the C language. For more details, please refer to the official answer.

What name should we give a variable?

A good variable name should clearly indicate the meaning of the variable.

When naming variables, we need to pay attention to their expressiveness and avoid using abbreviations.

Here we will briefly introduce the basic method of variable naming: Camel Case Naming Convention.

Camel case naming convention uses mixed-case letters to represent a variable. The first word is in lowercase, and the first letter of each subsequent word is capitalized.

For example: currentDate. The first word, current, is in lowercase, and the second word, Date, starts with a capital letter.

In this way, a variable that represents the current date leaps off the paper.

This naming convention is generally used for important and commonly used variables, while temporary variables can be simplified as long as they do not cause duplication.

Batch Declaration Method

Now let's declare three variables:

var a int // Declare an integer variable called a
var b int // Declare an integer variable called b
var c int // Declare an integer variable called c

The observant students may have noticed that all three variables, a, b, c, are of type int.

In that case, we can use a comma to connect the variable names and reduce the amount of code.

var a, b, c int // Declare three variables a, b, c as integers

But what if the three variables have different types?

var a int    // Declare an integer variable called a
var b string // Declare a string variable called b
var c bool   // Declare a boolean variable called c

We seem to have encountered a similar situation when importing packages. Many packages with different names need to be imported together, so we can use a similar writing method:

var (
    a int
    b string
    c bool
)

Note that this kind of declaration behavior similar to importing packages is generally used to define global variables.

Default Initialization

In Go, all variables are given initial values when they are declared. Let's explore what the initial values of variables are!

Create a file named varExercise.go in the directory ~/project.

touch ~/project/varExercise.go

Write the following code to the file:

package main

import "fmt"

func main() {
    var a int
    var b string
    var c bool
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}

You can try running it yourself and see if it matches the table below.

Types of initial values are summarized as follows:

Keyword Explanation Initial value
int Integer 0
string String ""
bool Boolean false

Standard Initialization

Since the type of a variable can be determined by its initial value, can we change the default value or an already declared variable?

var a int = 1
var b string = "labex"
var c bool = true

a = 233
b = "labex"
c = false

As shown above, we just need to add = after declaring the variable, followed by an initial value that is compatible with the variable type. If you want to change the value, just use the variable name followed by = and another value of the same type.

Modify the varExercise.go file:

package main

import "fmt"

func main() {
    // Declare and initialize
    var a int = 1
    var b string = "labex"
    var c bool = true

    // Print the variables
    fmt.Println("Before modification:")
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)

    // Modify the variables
    a = 233
    b = "labex"
    c = false

    // Print the modified variables
    fmt.Println("After modification:")
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}

After running the code, the output is as follows:

$ go run varExercise.go
Before modification:
1
labex
true
After modification:
233
labex
false

You can try running it yourself and modify the initial values.

We just mentioned that the initial value assigned to a variable must be of the same type as the variable declaration. What will happen if they are different?

For example, let's assign "labex" as the initial value to the a variable:

package main

import "fmt"

func main() {
    var a int = "labex"
    fmt.Println(a)
}

Run the code:

$ go run varExercise.go
## command-line-arguments
./varExercise.go:6:12: cannot use "labex" (type untyped string) as type int in assignment

As shown in the figure, we cannot assign a non-typed string type such as labex to a variable of type int. This is because Go is a strongly typed compiled language and cannot be compiled.

Type Declaration by Inference

Since Go can determine the type of a variable by its initial value, can we simplify the process of type declaration by eliminating the step of explicitly specifying the type?

package main

import "fmt"

func main() {
    // var a int = 1
    var a = 1 // Type is inferred
    fmt.Println(a)
}

Now you don't even need to use the var keyword to define a variable.

This way of declaring and initializing a variable can also be combined with the batch declaration method we mentioned earlier:

a, b, c := 0
// Declare variables a, b, c as integers and assign an initial value of 0
a, b, c := 0, "", true
// Declare variables a, b, c as integers, string, and boolean, respectively

Short declaration is very convenient, but be careful that := is not an assignment operation. It is a way to declare variables and is unique to Go, used to declare and initialize local variables inside a function. The type of the variable will be automatically inferred based on the expression.

Sometimes we write the following code:

func main() {
    a := 1
    println(a)
    a := 2
    println(a)
}

The compiler will tell you that there is an error in the code because the variable a has been redeclared. However, if it is written in the following way:

func main() {
    a := 1
    if true {
        a := 2
        println(a) // Output: 2
    }
    println(a) // Output: 1
}

There is such an output because the a with a value of 1 above and the a with a value of 2 below are not in the same variable scope (within the same curly braces), so the compiler treats them as two different variables.

The compiler will not point out your mistake, but there will be unexpected output.

In Go, it is stipulated that:

Each statement outside a function must begin with a keyword (var, func, etc.).

Therefore, the short variable declaration can only be used to declare local variables, and cannot be used to declare global variables.

So what is a global variable and what is a local variable?

This involves the concept of variable lifetime, which will be explained in the next section.

Variable Scope

Variable scope refers to the range at which a variable in a program is effective, that is, how it can be used.

You must have noticed that if we declare a variable but don't use it, the code will not compile.

In other words, when Go is compiled, it checks whether each variable has been used, that is, whether it has been used within its scope.

We can simply divide variables into three types based on their declaration positions:

  • Variables defined within a function, called local variables
  • Variables defined outside a function, called global variables
  • Variables defined within a function definition, called formal parameters

Local Variables

In this section, most of the variables we define are local variables:

package main

import "fmt"

func main() { // Function body
    var a int = 1 // Local variable
    fmt.Println(a)
}

Local variables are defined within the function body, such as a defined within the main function. The scope of variable a is limited to within the main function.

At the same time, if the variable is not used in the main function, the compiler will throw an error.

Global Variables

However, it is also possible to define a global variable.

package main

import "fmt"

var a int = 1 // Global variable
func main() { // Function body
    fmt.Println(a)
}

Global variables are defined outside the function body, and their scope covers the entire program. Even if they are not called in any function, an error will not be reported by the compiler.

You can think about why global variables will not produce errors even if they are not called.

Answer

This is because the global variable may be called in another package.

About formal parameter variables will be explained in detail in the subsequent function-related courses.

Variable Lifetime

Birds that fly away, hide the span. Scheming rabbits die, and hounds will stew. - Records of the Grand Historian

When a variable has completed its mission, it should be destroyed to reduce memory usage.

  • Global variables: The lifetime of a global variable is consistent with the entire program runtime. When the program stops running, the global variable is cleared from memory.
  • Local variables: When there is no way to access a variable, its memory space will be reclaimed.

Such a design is the key to Go's high speed and efficient use of space.

During the lifetime of a variable, it cannot be redeclared.

You can write the following in varExercise.go:

package main

import "fmt"

func main() {
    var a int = 1 // Local variable, lifetime is limited to the entire main function
    var a int = 2 // Redefinition
    fmt.Println(a)
}

After running the code:

go run varExercise.go
## command-line-arguments
./varExercise.go:7:9: a redeclared in this block
previous declaration at ./varExercise.go:6:9

The compiler tells us that a is defined again.

Constants

Many things in life are like constants. We can perceive them but cannot change them.

If a variable will not change during the entire program runtime, then we should define it as a constant.

Constants are very similar to variables, and you can even think of them as variables with immutable values.

When declaring a constant, we only need to replace the var keyword with the const keyword.

const Pi = 3.14159 // Using type inference initialization

What will happen if we try to modify a constant?

package main

import "fmt"

func main() {
    const Pi = 3.14159
    Pi = 2
    fmt.Println(Pi)
}

Run the code.

$ go run constExercise.go
## command-line-arguments
./constExercise.go:7:8: cannot assign to Pi

The compiler tells us that the value of Pi cannot be reassigned.

When declaring a constant, we must provide an initial value.

And the initial value assigned to a constant must be fixed at compile time.

User-defined function return values are not considered fixed in Go.

var a int = 1
// Value is fixed, declaration is valid.
const Pi = 3.14159
// The calculated value is also fixed, the declaration is valid.
const c = 1 / Pi
// Fixed return value from built-in function is valid.
const le = len("labex")
// The return value of the user-defined function is not fixed, the declaration is invalid.
const le = getLen("shiyanlou")
// a is a variable value that is not fixed, the declaration is invalid.
const k = a

Whether a constant declaration is valid can be summarized in the following table:

Declaration Type Valid
Fixed values and fixed value expressions Valid
Non-fixed values (variables) and their corresponding expressions Invalid
Built-in function (len()) receives a fixed value and fixed value expressions Valid
User-defined functions Invalid

Summary

Let's review what we learned in this lab:

  • The ways to declare variables
  • The ways to initialize variables
  • The concept of variable lifetime
  • The use of constants and whether their declarations are valid

In this lab, we have reviewed the basic usage of variables in Go, demonstrated the ways to declare and use variables in different situations, and introduced constants. In the next lab, we will learn about operators and use variables for calculations.

Other Go Tutorials you may like