Go 101: Variables, Constants and Scopes
Tags: go, tutorial, beginners, programming
Published: 2022-11-15 15:08:20

In programming, **variables** are placeholders holding values. A variable in Go is associated with four elements: a **keyword**, a **name**, a **type** and a **value**. Variables are particularly useful to hold values we might want to use throughout our program, and to avoid using literal values everywhere. 

Asides from variables, Go offers the possibility to use **constants**. Constants also have the ability to hold values. However, the value associated to a constant cannot be changed once it has been assigned, as opposed to variables.

In this tutorial, we will also go through the concept of **scope**. A scope defines the boundaries within which our variables and constants can be accessed. We are going to see that Go is characterised by a **lexical** scope, defined within curly brackets. Go is also characterised by a **package** scope, a feature that we will study in a later tutorial when we speak about functions.

## Variables


As mentioned in the introduction, a variable is characterised by four elements: a **keyword**, a **name**, a **type** and a **value**.

In Go, a variable definition starts with the **_var_** keyword.

Following the _var_ keyword, a name for this variable must be chosen. In Go, there is an idiomatic set of rules that should be followed in order to correctly name a variable. Names should always start with a **letter**. The subsequent characters can either be other letters, numbers or underscore. In addition, the naming convention dictates the usage of camel case for compound names (eg. minNumber).

As Go is a statically-typed language, each variable needs to be assigned a **data type**, and that type cannot be changed throughout the lifetime of this variable. Those types can be any of those we have seen so far (string, number, boolean), or any other more complex types we will see later on.

Finally, our variable needs to be assigned a **value**. This value can be a literal value (for example, 1 or "Hello, World!"), but any another variable or constant can be assigned as a value too. The value assignment is independent from the variable declaration (where we define the keyword, the name and the type). Therefore, this last step can actually be performed later on in the program, after the variable declaration.

Programmatically, a variable is defined as followed.

`var hello string = "Hello, variable!"`

As you can see, we have used our var keyword, the name of our variable is _hello_, the type of our variable is a _string_ and the value is _"Hello, variable!"_. 

As mentioned earlier, we could have divided the declaration and the value assignment into two separated lines.

```
var hello string
hello = "Hello, variable!" 
/* We use the name of our variable to assign a value to it, using the = sign */
```

As the name suggests, we can **change the value** assigned to our variable at any point in our program (but not its type). To do so, we just need to reassign a value to that variable.

```
var x string = "Original value"
x = "Substituted value"
fmt.Println(x)
// This will print "Substituted value" to the console
```

If we run this program, it will output "Substituted value" to the console. It is indeed the value we have reassigned to our variable _x_ in the second line of our program.

In fact, there are **shorter ways** we can use to define a variable. As a convention, those shorter versions should be used whenever it is possible.

Firstly, we could **remove the type** from our declaration. Go’s compiler is indeed capable of inferring the type of a variable by looking at the value being assigned. This however only works if we declare and assign a value to our variable in the same line. The program wouldn’t compile otherwise.

```
var hello = "Hello, variable!" 
// Go will infer that our variable is of type string
```

There is a way to shorten our declaration even more, by **removing the keyword** _var_. To do so, we also need to change the assignment operator from = to **:=**. Again, we can only use this method if we declare and assign a value to our variable in the same line.

`hello := "Hello, variable!"`

This method is much shorter than the previous ones, and is considered idiomatic. Therefore, you should use it whenever it is possible.

## Constants


Similarly to variables, constants are made of four elements: a **keyword**, a **name**, a **type** and a **value**. As the name suggests, once we have assigned a value to a constant, no value can be reassigned to that constant. It makes constants very useful to hold stable values throughout the execution of your program, such as mathematical constants.

To define a constant, you will need to use the **_const_** keyword.

`const pi float64 = 3.1416`

As the value of a constant cannot change, reassigning this pi constant would produce a compiling error.

Similarly to variables, it exists a shorthanded version for declaring a constant. You can do so by **removing the type** from the declaration.

`const pi = 3.1416`

It is however impossible to remove the const keyword from the declaration. Go would indeed assume that we are trying to define a variable instead of a constant.

## Multiple definitions


Similarly to other programming languages, it is possible in Go to define multiple variables (or constants) at the same time.

```
var (
     first = "I"
     second = "love"
     third = "Go."
)
```

It is important to notice several things here. Firstly, each variable (or constant) should be on **its own line**. Secondly, we **voluntarily omitted the type** (it would be totally valid to declare it). Lastly, as we use the keyword var (const for constants), we use the **= assignment operator** (and not the := operator).

## Scopes


In programming, a scope defines the **boundaries within which we can access a variable** (or constant). 

Without scopes, one major issue could arise in our programs. This issue is known as **naming conflict**. Those conflicts arise when we are trying to declare a variable with a name that is already used somewhere else in our program by another variable. Unknowingly, we would then reassign the value of the first variable. This can lead to awkward and hard to track bugs. 


To avoid those issues, Go is using what we call a **lexical (or static) scope**. In other words, the possibility to access a variable (or constant) depends on the location **where this variable is declared** in the first place. This lexical scope is the opposite of a dynamic scope where we can access variables declared in other functions, as long as those functions are located below in the stack.

In Go, this lexical scope is **restricted by a block**. This block itself is **bounded by curly braces**. In other words, a variable (or constant) can only be accessed within the block in which it is defined. For example, a variable defined inside of a function would only be accessible inside this function, and not outside of it. 

This lexical rule also includes **any child scope** within the boundaries of the scope. For example, we could access the variables defined in a function from a conditional block, if this conditional block is located inside that function (the conditional block being the child scope).

It is also worth mentioning that a variable (or constant), declared in the **global scope** (outside of any function or condition blocks), will be accessible everywhere in our program. The global scope is indeed the parent scope of all the other scopes defined in our program. It is however advised to use this global scope with caution, as using it could lead to naming conflicts in our programs. 

It is also important to note that any variable or constant declared in the global scope should be declared with a keyword (const or var). Failing to do so will lead to a compiler error.

In order to illustrate this concept of scope, let’s create the following two programs.

{% gist https://gist.github.com/Agilulfe/c7593b2253fc3a825d4e70e4dbea3e36 file=main.go %}

In this program, we define two functions. The first function, _main_, will access our variable _x_ defined in the global scope as well as calling our second function. This second function, _testScope_, accesses the same global variable, and print it to the console too (with a "test" string concatenated).

{% gist https://gist.github.com/Agilulfe/c3eb4fc340615a29e99f92a2748bf582 file=main.go %}

In this program, we define the variable _x_ inside the _main_ function. We also call the _testScope_ function from our _main_ function. _TestScope_ tries to print _x_ to the console as well. However, writing the program in such a way will provoke a compiling error, as _x_ is unaccessible from the testScope function. Indeed, _x_ is defined inside the block of the main function, and can only be accessed inside that same block.

## Conclusion


In this tutorial, we have continued our journey through the basic concepts of Go. We have explored the concepts of variables, constants and scopes. Mastering those concepts is fundamental in order to continue our journey, and explore the advanced parts of the Go language. In our next tutorial, we will explore control structures in Go.