Go 101

Basic Types

Guillaume Jacobs
8 min readAug 28, 2020
The official Go mascot, credit: Renee French
The official Go mascot, credit: Renee French

Similarly to any other field, Computer Science is made of fundamental concepts. One of those core elements is the concept of data type. As most of its fundamental counterparts, it is very hard to give a satisfying definition to what is a data type.

However, a functional definition would be to define a type as being a set of similar values (they have similar properties), on which we can apply an homogenous and defined set of actions, and that are stored on the machine in a similar way.

A classical example to illustrate data types is animal species. Let’s say for example that one of our type is the cat specie, while the other is the bird one. Even though each individual cat is different, they are all part of the same specie (set). All the cats have similar properties (they have four legs and are fluffy), we can apply similar actions to them (sometimes, we can pet them) and they are “stored” the same way (usually around a blanket or a cardboard box). On the other hand, birds have different features (they can fly, they have feathers), we can perform different actions with them (I know for sure that my cat would never accept to be fed with seeds) and they tend to find their home on the branches of trees.

In this story, we are thus going to cover what are the basic types in Go, what kind of actions we can perform on them, and how they are stored on the machine. If you are new to Go, and have missed the first part of this tutorial, feel free to go and check it by clicking on the following link.

If you have already followed the first tutorial, I recommend you to create a new directory called types inside of your src directory. Inside of this newly created directory, create a new main.go file, where you will be able to write today’s code.

Numbers

Similarly to most programming languages, we can subdivide Go’s numbers types into two main categories: integers and floating-points.

Integers

If you have some maths background, you should already know what an integer is. For those of you who don’t (or, if you have slept through school), integers are part of the set of whole numbers (thus, not having decimal places), that hold values that can be negative, positive or equal to zero. An integer can thus be, for example, any of the following values: -25, 0, 17, 2020, …

If you work with integers, you will most likely only use the int type (signed integer). This is the classical 32 or 64-bits wide integer (depending on your machine). Other int types include int8, int16, int32 or int64 (the number part being the number of bits that they use).

Go also offers a uint type (unsigned integer) that only holds positive values, or zero. Similar to int, go has the uint8, uint16, uint32 and uint64 types.

Finally, and mostly as a reference, Go also possesses a uintptr type, which is basically an integer representation of a memory address (type that you will most likely never use, unless performing some magic with pointers).

Floating-points

As opposed to integers, floating-points numbers are numbers with a decimal component. 3.14, 2020.08, -123.5 or 5.0 are all floating-points. There is two floating-points types in Go: float32 (also called single precision float) and float64 (double precision float), respectively for 32 or 64 bits-wide floating-points. By default, you should stick with float64.

If floating-points are often referenced to as single or double precision, it is for a reason. As opposed to integers, floating-points are inexact numbers (and using a float64, as you can guess, offers a better precision). For example, you would expect that 1.51–1.50 would result into 0.01. However, running the following program gives an other result.

This program will print false to the console if we run it

The fmt.Println(1.51–1.50 == 0.01) will print to the console a boolean (more on this later in this story). If, in Go, 1.51–1.50 is indeed equals to 0.01, you should see true being printed to your console. However, after running this program, we see the value false being printed to the console.

This shows that floating-points are indeed non-exact numbers and you should be very careful when performing conditional logic involving floats.

As a side note, it is also worth mentioning that two other types, complex64 and complex128, are built respectively on top of the float32 and float64 types. Those types deal with complex numbers arithmetic.

Operations with numbers

Go supports basic arithmetic operation that we can perform on numbers. Those operations includes:

  • Addition, using the symbol +
fmt.Println(1 + 1)// This would print 2 to the console (this is also a comment in Go)
  • Subtraction, using the symbol -
fmt.Println(1 - 1)// This would print 0 to the console
  • Multiplication, using the symbol *
fmt.Println(2 * 2)// This would print 4 to the console
  • Division, using the symbol /
fmt.Println(2 / 2)// This would print 1 to the console
  • Remainder of a division, using the symbol %
fmt.Println(3 % 2)/* This would print 1 to the console. It is pretty useful to check if a number is even or odd (also, this is a multi-line comment) */

Strings

In our “Hello, World!” tutorial, we have already seen what a string is. It is any sequence of characters that is placed in between double quotes (single quotes being used for what is called a rune, namely a single character). Strings can also be defined with backticks (``). The latest is for example useful if you want to create multi-lines strings. If you come from a language like Python or JavaScript, it is thus very important to always use double quotes (or backticks) instead of single quotes to define a string.

One of the main property of a string is its length. This length characterises the number of characters that a string possesses. The length can be zero (we speak about an empty string), or any number above.

Usually, but it is not always true, each element of a string is made of a byte.

Operation with strings

There is a series of basic operations we can perform with strings.

  • Calculate the length of a string with the len built-in function.
fmt.Println(len(""))// This would print 0, as it is an empty stringfmt.Println(len(" "))// This would print 1, as a space is considered a characterfmt.Println(len("Go is an amazing language"))// This would print 25
  • Accessing a particular element (character) of the string, with the following [i] notation placed after our string, where i is the index of the element we want to access (and i = 0 being the first element of the string).
fmt.Println("Learning Go is a good investment"[1])// This would print 101 to your console

Again, if you come from a language like Python or JavaScript, you would have expected to see the character ‘e’ (the second element of our string) to be printed to the console. However, Go doesn’t return the actual character when we try to access it, but the ASCII value representing this specific character. In this specific case, the character ‘e’ is represented by 101.

  • Concatenate two, or more, different strings together, using the + symbol.
fmt.Println("Hello, " + "World!")// This will print Hello, World! to the console 

Booleans

The last basic type that we have in Go, similarly to the other programming languages, is the boolean type. This type is used to represent the true or false values in our programs. On the machine, those values are represented by a one bit integer, respectively 1 and 0.

The boolean values are heavily used when performing conditional logic in our programs. We have already seen one example earlier, when we demonstrated that floating-point numbers are inexact (our program printing false). Another example where we would receive a boolean value would be for example to check if a string is a subset of another string (‘at’ being a subset of ‘cat’ for example, and this would return true).

Conditional operators

Go uses three conditional operators, that are also common to most of the programming languages.

  • && : This characterises the logical And. A program using a logical && will return true if all the elements are true.
fmt.Println(true && true)// This returns truefmt.Println(true && false)// This returns falsefmt.Println(false && false)// This returns false
  • || : This characterises the logical Or. A program using a logical || will return true if at least one of the elements is true.
fmt.Println(true || true)// This returns truefmt.Println(true || false)// This returns truefmt.Println(false || false)// This returns false
  • ! : This characterises the logical Not. A program using a logical ! will return true if the value is false. On the other hand, it will return false if the value is true. It is for example used to check if a task still need to be performed or not.
fmt.Println(!true)// This returns falsefmt.Println(!false)// This returns true

Playing around with types

If you would like to play more around types, there is an extremely interesting built-in package that you can use in your program. This package is called reflect. In this package, one of the defined function is TypeOf. This function is given a value and it will return the type of this value.

As Go is a statically-typed language, it can be useful to check the type of a variable you are using in your program, especially when your program fails to compile. It can also be interesting to experiment with edge cases, and see what would be the result of this experiment. One of those cases would be to check what happens if you add a float to an int, as shown with the following example.

TypeOf allows you to check the type of a value

In today’s tutorial, we have seen the three basic types of Go. Most of the other types that we will see later are actually built on top of those three basic types. Below, you can find a gist with all the code we have been using in this tutorial. I really encourage you to run the program yourself, and play around with it to test different things. Getting familiar with the different types is very important for the rest of our journey. If you have any question, feel free to ask them in the comments section below.

In the next lesson, we will cover the concepts of variable, constant and scope in Go. I am looking forward to it and I hope you will enjoy it!

Resources

Here, you can find all the resources we have been using in this tutorial.

--

--

Guillaume Jacobs

Belgian Software Engineer living in Munich, Germany. Tech and sciences enthusiast.