Log In

Data Types in Go

Data Types in Go
10.04.2024
Reading time: 9 min
Hostman Team
Technical writer

Go (Golang) is a multi-threaded programming language developed by Google in 2009. Its syntax is similar to that of the C language, and it is designed to make it easier to write highly efficient software.

In this tutorial, we'll look at the different Golang data types and give recommendations for choosing them.

Prerequisites

  • A machine with the Go language installed.

You can run Go on your local computer or on a cloud server on Hostman which can be securely managed via SSH without the need for logins and passwords.

Declaring Variables

Declaring a variable is the process of creating and assigning it a name and data type. In Go, variable declaration is done with the var keyword, as well as using the := operator.

The syntax for variables declaration in Go using var is:

var variable_name data_type

And this is what declaring variables through var looks like:

var FirstName string
var salary float32

Now, let's look at the second way of declaring variables, namely with initialization, i.e., indicating the initial value when creating them.

The syntax for declaring variables with initialization is as follows:

var variable_name data_type = value

This is what it looks like:

var FirstName string = "Mike"
var salary float32 = 70000

In addition to the above, there is a short way to declare variables using the := operator. This method automatically sets the type of the variable when specifying the value. Syntax:

variable_name := initial_value

Examples:

FirstName := "Mike"
salary := 70000

In the output, you will see that the FirstName variable is automatically assigned the string type, and the salary variable is automatically assigned the int type.

Type string for Mike
Type int for 70000

...Program finished with exit code 0
Press ENTER to exit console.

Basic Data Types

First of all, let's look at the main Golang data types.

Integer data types

Integer data types in Go describe integer values, which can be positive, negative, or zero. There are several types of integer data in Go, which differ in byte size. Let's look at each of them in more detail in the table below.

Type

Description

Range

int8

8-bit signed integers. 

from -128 to 127

int16

16-bit signed integers. 

from -32,768 to 32,767

int32

32-bit signed integers. 

from -231 to 231-1

int64

64-bit signed integers. 

from -263 to 263-1

int

32-bit or 64-bit signed integers (depending on the platform). Used by default with integer values.

As int32 or int64 (depending on the platform)

uint8

8-bit unsigned integers.

from 0 to 255

uint16

16-bit unsigned integers.

from 0 to 65,535

uint32

32-bit unsigned integers.

from 0 to 232-1

uint64

64-bit unsigned integers.

from 0 to 264-1

uint

32-bit or 64-bit unsigned integers (depending on the platform).

As uint32 or uint64 (depending on the platform)

In addition to those listed, there are also byte and rune. They are equivalent to uint8 and int32, respectively.

Examples of declaring integer variables:

var x int16 = 45000
var y uint = 73000
var z byte = 4

Real data types

Real data types are used to store fractional numbers. Go offers two options: float32 and float64.

float32 takes 4 bytes in memory and can store floating point numbers from -3.4028235E+38 to 3.4028235E+38 with a precision of 7 decimal places;

float64 occupies 8 bytes in memory and can store floating point numbers from -1.7976931348623157E+308 to 1.7976931348623157E+308 with a precision of 15 decimal places.

It is important to understand that real numbers in a computer are represented in binary form, and therefore may be inaccurate. This may result in rounding errors when performing operations on such numbers. Therefore, when working with them, it is important to take into account the peculiarities of their representation in a computer and take measures to avoid rounding errors.

Examples of declaring real variables:

var x float32 = 3.14
var y float64 = 3.1415926535897

String data types

String data types in Go are used to store character strings. Each character in a string represents a sequence of bytes in memory.

Strings are immutable objects in Go. This means that once a string is created, its contents cannot be changed. However, you can create a new string by combining several existing strings.

Go also has special characters. Some of them are:

  • \n - line feed or newline
  • \t - tab
  • \" is a double quote
  • \' is a single quote
  • \\ is a backslash

In addition, it is possible to use Unicode characters. To do this, you can use a sequence of characters in the \uXXXX format, where XXXX is the hexadecimal value of the character's Unicode.

Examples of declaring a string variable:

var exampleText1 string = "Hello, user1!"
exampleText2 := "Hello, user2!"

Boolean data type

Go has a boolean data type, bool, which can take the values true and false.

This data type can be used to store the values of logical expressions, for example in conditional if and switch statements, as well as in logical operators such as && (logical AND), || (logical OR) and ! (logical NOT).

For example, we can use the boolean data type in the following code:

age := 21
isAdult := age >= 21
fmt.Println(isAdult)

When executing the code, the output will show true.

Image7

Composite data types

Next, let's look at composite types in Go.

Arrays

Arrays in Go are used to store a fixed number of elements of the same type. The main difference from other languages is that here arrays are values, not references to data.

To define an array, you must specify the element type and the number of elements in square brackets. For example:

var exampleArr [4]int = [4]int{2, 5, 7, 9}

Array elements are accessed by index, starting from 0:

fmt.Println(exampleArr[0])

Arrays in Go also support iteration using a for loop:

for i := 0; i < len(exampleArr); i++ {
    fmt.Println(exampleArr[i])
}

Slices

Slices are a reference data type in Golang that represents a dynamic array of elements stored in memory. They are very similar to arrays, but unlike them, the slices' size can be adjusted during program execution, and they are references to data rather than values.

A slice is defined using the following syntax:

var slice []T

Where T is the type of slice elements, and slice is a variable that stores a reference to the slice.

An empty slice can be declared like this:

emptySlice := []int{}

To initialize a slice, you can use the make function, which creates a new slice of a given length:

slice := make([]int, 5)

The example above creates a slice of five int elements.

In addition, the make function has a third optional parameter that denotes capacity. It is used to pre-specify the amount of memory that will be allocated to store slice elements. Due to the reduction in the number of memory allocation operations, the load on the processor is significantly reduced.

For example:

slice := make([]int, 10, 20)

This code snippet creates a slice containing 10 elements of the int data type and with a pre-allocated capacity of 20 elements. This means that the slice initially contains 10 zero-initialized elements, and can be expanded to a maximum of 20 elements without the need to allocate additional memory. If suddenly the number of slice elements becomes more than 20, then Go will automatically allocate a new memory block that will be 2 times larger than the previous one.

The capacity approach is recommended when the user knows in advance the maximum number of elements that will need to be stored in the slice.

Indexing is used to access elements, just like with arrays.

Structures

In short, structures are a collection of fields. The fields, in turn, characterize various attributes of objects.

To declare a structure in Go, you use the keyword type, followed by the name of the structure and its definition in curly braces. For example, we will declare a structure representing information about a person:

type Person struct {
    Name string
    Age int
    Address string
}

To create a variable that stores the values of a structure, you need to use the var keyword and the name of the variable. The variable name is then followed by the structure name, followed by curly braces with the structure field values in the form field_name: value. For example:

var person1 Person
person1 = Person{Name: "John", Age: 30, Address: "123 Main St."}

Here we declare a variable person1 of the Person type and assign it values for each field. You can also use a short form of structure initialization:

person2 := Person{Name: "Jane", Age: 25, Address: "456 Elm St."}

Structure fields are accessed using the dot (.) operator. For example, to get the name person1, you need to write:

person1.Name

Structures can contain other structures within themselves and even references to themselves (so-called recursive structures). In addition, they can implement interfaces.

Maps

A map is a reference data type that is used to represent an unordered set of key-value pairs. The keys in the map must be unique, but the values may be repeated.

To create a map, the built-in make() function is used, which is passed the key and value types. The following code creates an empty map with string keys and int values:

m := make(map[string]int)

To add an element to a map, you can use the following entry form:

m[key] = value

For example:

m["apple"] = 3
m["banana"] = 5

To get the value of an element by key, use the following notation form:

value := m[key]

For example, to get the value of an element with the key apple:

count := m["apple"]

If an element with the specified key is not in the map, the default value will be returned.

To remove an element from a map, you can use the built-in delete() function. The following code removes the element with the key apple:

delete(m, "apple")

In Go, maps are implemented as hash tables, so the order of elements in a map is not fixed and can change each time the program is executed. You should also pay attention to the fact that the map is not thread-safe, therefore, when accessing the map in parallel, you must use access synchronization mechanisms (mutexes or channels).

Pointers and Interfaces

Pointers 

Pointers are needed to interact with variables that store addresses in memory. They can be defined by using the & symbol in front of the variable, and the * symbol is used to get the value pointed to by the pointer.

Example:

var myInt int = 42
var myIntPointer *int = &myInt
fmt.Println(*myIntPointer)

The output of the program is shown in the picture below.

Image8

Interfaces

Interfaces are used to define a set of methods that a data type must implement. Interfaces can be used to abstract away a specific data type and to implement polymorphism. To create an interface in Go, you need to define a set of methods that the data type must implement.

Example:

type Writer interface {
    Write([]byte) (int, error)
}

This defines the Writer interface, which must have a Write method with an argument of type []byte and return the number of bytes written and an error.

Conclusion

In this tutorial, we looked at the main data types in Golang. In addition, we have provided declaration syntax and working examples for each of them.

We hope that this guide and tips will help you learn how to choose the right data types in your code, leading to improved performance of the programs you develop.


Share