Go: Variables

Matthew Sedlacek
9 min readJan 4, 2021

--

Photo by Mitchell Luo on Unsplash

Overview of Go

Go was created in 2009 by Robert Griesemer, Rob Pike, and Ken Thompson at Google. Go is an open-source, statically typed, compiled language and is commonly referred to as Golang. Some of Go’s key benefits include “…memory safety, garbage collection, structural typing, and CSP-style concurrency” (Built In).

This blog is designed to show how to work with variables in Go and will cover the following topics:

  1. Declaring variables
  2. Redeclaring variables
  3. Shadowing
  4. Naming variables
  5. Scope
  6. Converting data types
  7. Constants

**Some examples and overall structure of this blog come from Free Code Camp’s “Learn Go Programming — Golang Tutorial for Beginners” course on YouTube. **

Declaring Variables

If we wanted to declare a variable called i that has integer as its type, we could write the following.

package mainimport (     "fmt")func main() {     var i int}

Next, to assign this variable to an integer of 16 and print that variable to the console, we could write the below variable declaration. We’ll call declaring variables like this the multi-line approach.

package mainimport (     "fmt")func main() {     var i int
i = 16
fmt.Println(i)
}// Terminal command to run this program is go run main.goOutput: 16

Other Ways to Declare Variables

Another way to write the above variable declaration would be to put everything on a single line. We’ll call declaring variables like this the single-line approach.

package mainimport (     "fmt")func main() {     var i int = 16     fmt.Println(i)}// Terminal command to run this program is go run main.goOutput: 16

Lastly, Go’s compiler is able to determine i’s data type based on the value we are setting i equal to with “:=”. In the example below, i will have a data type of integer. We’ll call declaring variables like this the colon-equals approach.

package mainimport ("fmt")func main() {     i := 16     fmt.Println(i)}// Terminal command to run this program is go run main.goOutput: 16

When to use each type of variable declaration

Now that we know that there are multiple ways to declare variables; multi-line, single-line, and colon-equals approaches. We should discuss when to use each type.

The multi-line approach is useful when you want to declare a variable but don’t want to initialize it. For example, the value of the variable is being assigned in a for loop later in the function, and making it equal to something outside the loop is unnecessary.

The single-line approach should be used when Go doesn’t have enough information to assign your desired data type. For example, say that we want our i variable from before to be a float32 instead of an integer. We could simply change our variable declaration to var i float32 = 16 . Declaring variables in this way provides us with more control. It is also worth noting that if we are declaring variables at the package level we need to use this type of syntax because the colon-equals approach is not allowed by Go for package level variables.

The colon-equals approach is the least verbose approach and should be used within our functions when Go’s compiler is able to determine the correct data type of the variable.

package mainimport (      "fmt")func main() {// multi-line approach: useful for for loops     var i int     i = 14// single-line: useful for when you need control over the data type     var j float32 = 15// colon-equals: least verbose, use when Go's compiler is able to determine data type     k := 16     fmt.Println(i)// print statements for displaying value and type     fmt.Printf("%v, %T", j, j)     fmt.Printf("%v, %T", k, k)}Output: 14
15, float32
16, int

Block Variables

At the package level, we can also assign multiple variables together in a block. Notice how in the block, we don’t need to type the var keyword in front of each variable name. We can also assign multiple blocks at the package level. Creating block variables is useful when we want to show that certain variables are related to each other. See below for an example.

package mainimport "fmt"var (     playerName    string  = "Andre Agassi"     sponsor       string  = "Head"     worldRanking  int     = 1     stringTension float32 = 65.5)var (     matchesPlayed int  = 0)func main() {     fmt.Println(playerName, sponsor, worldRanking, stringTension, 
matchesPlayed)
}Output:Andre Agassi Head 1 65.5 0

Redeclaring Variables and Shadowing

Take a look at the code below. What do you think the console will output?

  1. 27
  2. 42
  3. 13
  4. An Error
package mainimport "fmt"
var i int = 27
func main() { var i int = 42 i := 13 fmt.Println(i)}

If you guessed that this would produce an error, great job. The reason that this code creates an error is that we cannot declare the same variable twice in the same scope. In this instance, i := is trying to declare and initialize a new variable called i. However, we declared i already in our main function and set it equal to 42.

To get the console to output to 13 we simply would need to replace := with just = . This reassigns the value of i to 13 rather than making a new variable and setting that variable equal to 13.

In order for the above to output 42. We would need to remove the i := 13 or i = 13 , if we fixed the error. Even though we already declared i in the package level our second i declaration is in a different scope. Go will output the variable with the inner most scope, which in our case is 42. The technical term for this in Go is shadowing. Moreover, the package level i is still available but being hidden by the variable declaration in the main function.

To output 27 we would need to print i before we declare i equal to 42 in the main function. See below for how this would look.

package mainimport "fmt"var i int = 27func main() {     fmt.Println(i)

var i int = 42
fmt.Println(i)}Output: 27
42

**Special Note: Go requires that we use all the variables we declare in our application functions. If we don’t use a variable, the application will produce a compile-time error. This is useful as it forces developers to remove unused code and keep applications clean. **

Naming Convention Determines Visibility

The naming convention of our variables is important because it determines the variables visibility within the application. The three naming conventions for variables are:

  1. Lowercase
  2. Uppercase
  3. Block

Lowercase variable names are scoped to the package. This means that the variable is only accessible in the package in which it’s declared and unavailable for use in any other package.

Uppercase variables are globally visible, which means that they can be used within the package in which they are declared and other packages within our application. This is because uppercase variables are exported from the package when compiled.

Block scope can be found when we declare variables within functions. This scope is only visible within the function and not the package or other packages.

See below for an example of all naming conventions types

package mainimport "fmt"//uppercase: globally visiblevar I int = 27// lowercase: visible to the package onlyvar (     playerName    string  = "Andre Agassi"     sponsor       string  = "Head"     worldRanking  int     = 1     stringTension float32 = 65.5)func main() {// block: only visible within the main function     var i int = 42     fmt.Println(i)     fmt.Println(I)     fmt.Println(playerName, sponsor, worldRanking, stringTension)}Output:42
27
Andre Agassi Head 1 65.5

Converting Data Types

Next we will discuss how to convert data types in Go. More specifically, we will cover converting integers to floats and converting integers to strings, which require different approaches.

Integers to Floats

To convert an integer to a float in Go you need to use a conversion operator. Go requires that you explicitly convert data types because it does not want to risk losing data through a conversion. In our example below, we will use float32 as a function to convert variable i to a float called j.

package mainimport "fmt"func main() {     var i int = 42     fmt.Printf("%v, %T\n", i, i)     var j float32     // conversion operator     j = float32(i)     fmt.Printf("%v, %T\n", j, j)}Output:42, int
42, float32

** Note: Converting from a float to an integer can result in data loss**

Integers to Strings

To convert an integer to a string in Go we need to add a package called “strconv”; found here. If we tried to use the conversion operator from before, we would get a unicode character. See bold items below for how to import the package and convert our integer to a string.

package mainimport ("fmt""strconv")func main() {     var i int = 42     fmt.Printf("%v, %T\n", i, i)     var j string     // use strconv package's str converter function to change from
an integer to a string
j = strconv.Itoa(i) fmt.Printf("%v, %T\n", j, j)}Output:42, int
42, string

Constants

Similar to other programming languages, Go allows for constant variables. Constant variables or constants are variables whose values are fixed and cannot be changed.

It’s important to note that constants use the same camel-case naming convention as normal variables. As you may remember with normal variables, the naming convention is important because it determines the variables visibility within the application. The same rules apply for constant variables.

To create a constant variable we need to use the const keyword rather than var we have been using. Let’s create one now!

package mainimport "fmt"
func main() { const firstConst int = 1 fmt.Printf("%v, %T\n", firstConst, firstConst)}Output:1, int

In the above main function we are creating a constant called firstConst with a type of integer. In addition to integers, constants can use any of the primitive types in Go which include boolean, numeric, and text. More information on primitives can be found here. Constants cannot use what are called the collection types; Arrays, Slices, Maps, Structs.

Another characteristic of constants is that their values must be assignable at compile time. What this means is that we cannot have our values equal to functions that will be calculated at run time. For example, const newestConst float64 = math.Sin(1.98)would produce an error.

Similar to regular variables, constant variables also have the same behaviors regarding shadowing and types being inferred. However, what’s unique about constants that you cannot do with variables is implicit conversions like the example below. This topic is discussed further in my primitives blog.

package mainimport (     "fmt")func main() {     const m = 10     var n int16 = 25     fmt.Printf("%v, %T\n", m+n, m+n)}Output:35, int16

The last topic we will discuss is constant variable blocks. Constant variable blocks are similar to regular variable blocks in overall structure. They differ in that they use the const keyword as well as a few other ways we will discuss below.

package mainimport (     "fmt")const (     _ = iota     doctor     lawyer     developer     dogSitter     accountant)func main() {     var occupationType int = lawyer     fmt.Printf("%v\n", occupationType == lawyer)     fmt.Printf("%v\n", lawyer)}Output:True
2

You may have thought that the first line in the constant variable block looks a little strange. The Go programming language has one right only variable which is the blank identifier and is displayed with an underscore. Having a blank identifier is beneficial because its saves memory in our program. Moreover, in the above example, by using a blank identifier, we are telling our program to ignore the first value. The other side of the equal sign may have been equally as confusing. Iota can be thought of as a counter and is scoped to the constant block. The value of iota on its own is 0. What’s unique about iota is that it assigns incrementing values to the other variables in the block. As you can see above, lawyer is the second variable after iota and therefore has a a value of 2. It’s also worth noting that you can use addition, subtraction, multiplication, division, remainder, bitwise, and bit-shifting operators with iota to create a fixed offset.

I hope this blog has kickstarted your journey as a Go Developer. Be on the lookout for future blogs, where I will deep dive into Go’s data types. I have also included some resources and learning materials for further exploration.

Learning Materials

Go Playground: Alternative for downloading Go on your local machine. Great resource for quick practice.

Go Packages: List of packages in Go

Resources

“Learn Go Programming — Golang Tutorial for Beginners.” YouTube, freecodecamp.org, 20 June 2019, www.youtube.com/watch?v=YS4e4q9oBaU.

“Why Go? 8 Engineers Discuss Golang’s Advantages & How They Use It.” Built In, 15 Oct. 2019, builtin.com/software-engineering-perspectives/golang-advantages.

--

--

Matthew Sedlacek

Software Engineer — Full Stack, JavaScript, ReactJS, Ruby on Rails, OO Programming (https://www.matthewsedlacek.com/)