Go 101: Basic Types
Tags: go, tutorial, beginners, programming
Published: 2022-11-08 15:00:57

Programming languages are made of fundamental concepts, shared by many of those languages, if not all of them. One of those core elements is the concept of data type. 

It is quite complicated to give a satisfying definition of what a data type is. A functional definition of a data type would be to define it as a set of items having **similar properties** (eg. they are numbers). On this set, we can apply an homogenous and defined **set of actions** (eg. accessing a part of an item via an index). Furthermore, the items in this set are **stored** in the computer in a similar way.

In this tutorial, we are going to cover the different categories of basic data types in Go, what kind of actions we can perform on them, and how they are stored in our computer. 

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 this [link](https://dev.to/agilulfe/go-101-hello-world-1in1). If you have already followed along the first tutorial, I recommend you to create a new directory called **types** inside 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

Our first category of data types are numbers. Unsurprisingly, all the data types inside this category have in common that they represent numbers. Similarly to most programming languages, we can subdivide Go's numbers types into two main sub-categories: integers and floating-points.

**Integers**

Most of you should already know what an integer is. Integers are part of the set of **whole numbers** (meaning that they don't have decimal places). Those integers hold values that can be negative, positive or equal to zero. Examples of integers are as follow: -25, 0, 17, 2020, …

If you work with integers in Go, you will most likely only use the **_int_ data type** (signed integer). This is the classical 32 or 64-bits wide integer (depending on your machine) that you would see in most programming languages. There are other integer types in Go, including int8, int16, int32 or int64. Each of them uses a different amount of bits, but they are fundamentally the same.

Go also has a **_uint_ type** (unsigned integer). This type can only hold positive values, or zero. Similarly to the signed integers, Go also has built-in uint8, uint16, uint32 and uint64 types.

Finally, and mostly as a reference for you, Go also has a built-in uintptr type. This type is used for creating integer representation of a memory address. You will most likely never use this type, unless you are adventuring yourself into the realm of advanced pointers logic.

**Floating-points**

As opposed to integers, floating-points numbers are numbers with a **decimal component**. 3.14, 2022.11, -123.5 or 5.0 are all floating-points. 

There are two floating-points types in Go: **_float32_** (also called single precision float) and **_float64_** (double precision float). Those two types respectively use 32 or 64 bits. 

By default, you should stick with float64 as it offers more precision (unless you are in a memory-constrained environment). Indeed, and as opposed to integers, floating-points are **inexact numbers**. 

In the following example, we are going to demonstrate this point.

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

You would expect that 1.51 – 1.50 would result into 0.01. However, running this program gives an other result. The `fmt.Println(1.51–1.50 == 0.01)` will print to the console a boolean. If, 1.51 – 1.50 was 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 result shows that floating-points are indeed non-exact numbers and you should be very careful when performing conditional logic involving floats.

Similarly to uintptr with int, complex64 and complex128 are two other floating types built respectively on top of the float32 and float64 types. Those types deal with complex numbers arithmetic and you will probably not use them.

**Operations with numbers**

Go supports basic arithmetic operations to be performed on numbers. Those operations include:

- **Addition**, using the symbol +

```
fmt.Println(1 + 1)
// 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. 
Also, this is a multi-line comment in Go */
```

## 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**. Strings can also be defined within backticks. Defining a string with backticks can be useful if you want to create multi-lines string literals. 

It is important to note that single quotes are only used to define what is called a **rune**, another built-in data type that represents a single character. If you come from a language like Python or JavaScript, it is therefore very important to always use double quotes (or backticks) in Go instead of single quotes when defining a string literal.

One of the main property of a string is its **length**. This length is defined by the number of characters that a string possesses. The length starts from zero (an empty string), and can go to any integer above.

Usually, but it is not always true (eg. Chinese character), each element of a string is stored as a single byte.

**Operation with strings**

There is a series of basic operations that 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 string
fmt.Println(len(" "))
// This would print 1, as a space is considered a character
fmt.Println(len("Go is an amazing language"))
// This would print 25
```

- **Accessing** a particular element (character) of the string with the [i] notation placed after our string, where i is the index (integer) of the element we want to access (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) being printed to the console. Indeed, Go doesn’t print 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 the ASCII value of 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 in Go is the boolean type. This type is used for representing **true** or **false** logical values in our programs, and more generally to perform conditional logic. In the computer, those values are stored as 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 of a boolean earlier, when we demonstrated that floating-point numbers are inexact.

**Conditional operators**

Booleans are often used in combination with conditional operators in order to represent more complex logic in your programs. Go has three built-in conditional operators.

- **&&** : This represents the logical **And** operator. A conditional logic using the And operator will evaluate to true if the elements on both sides of the operator are true or evaluate to true.

```
fmt.Println(true && true)
// This returns true
fmt.Println(true && false)
// This returns false
fmt.Println(false && true)
// This returns false
fmt.Println(false && false)
// This returns false
```

- **||** : This represents the logical **Or** operator. A conditional logic using the Or operator will evaluate to true if at least one of the elements on one side of the operator is true or evaluates to true.

```
fmt.Println(true || true)
// This returns true
fmt.Println(true || false)
// This returns true
fmt.Println(false || true)
// This returns true
fmt.Println(false || false)
// This returns false
```

- **!** : This represents the logical **Not** operator. A conditional logic using a logical Not operator will evaluate to true if the value after the operator is false or evaluates to false. On the other hand, the conditional logic will evaluate to false if the value after the operator is true or evaluates to true.

```
fmt.Println(!true)
// This returns false
fmt.Println(!false)
// This returns true
```

## Playing around with types

If you would like to play around with types more, there is an interesting built-in package that you can use in your program. This package is called **reflect**. In this package, you can make use of the TypeOf function. You can pass any value to this function and it will return the type of that value.

It can be interesting for example to experiment with edge cases, and check the resulting type with the TypeOf function. One of those cases could be to check what happens if you add a float to an int.

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

In today’s tutorial, we have covered the three basic categories of data types in Go. Most of the other built-in types in Go are actually built on top of those basic types.

Below, you can find a gist with all the code we have been writing 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 basics of Go is very important for the rest of our journey.

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

In the next tutorial, 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!