Arrays, slices, and maps
Arrays are one of the most widely used types of computer programming. They are lists of other types that you can access by using their position on the list. The only downside of an array is that its size cannot be modified. Slices allow the use of arrays with variable size. The maps
type will let us have a dictionary like structures in Go. Let's see how each work.
Arrays
An array is a numbered sequence of elements of a single type. You can store 100 different unsigned integers in a unique variable, three strings or 400 bool
values. Their size cannot be changed.
You must declare the length of the array on its creation as well as the type. You can also assign some value on creation. For example here you have 100 int
values all with 0
as value:
var arr [100]int
Or an array of size 3 with strings
already assigned:
arr := [3]string{"go", "is", "awesome"}
Here you have an array of 2 bool
values that we initialize later:
var arr [2]bool arr[0] = true arr[1] = false
Zero-initialization
In our previous example, we have initialized an array
of bool
values of size 2
. We wouldn't need to assign arr[1]
to false
because of the nature of zero-initialization in the language. Go will initialize every value in a bool
array to false
. We will look deeper to zero-initialization later in this chapter.
Slices
Slices are similar to arrays, but their size can be altered on runtime. This is achieved, thanks to the underlying structure of a slice that is an array. So, like arrays, you have to specify the type of the slice and its size. So, use the following line to create a slice:
mySlice := make([]int, 10)
This command has created an underlying array of ten elements. If we need to change the size of the slice by, for example, adding a new number, we would append the number to the slice:
mySlice := append(mySlice, 5)
The syntax of append is of the form ([array to append an item to], [item to append]) and returns the new slice, it does not modify the actual slice. This is also true to delete an item. For example, let's delete the first item of the array as following:
mySlice := mySlice[1:]
Yes, like in arrays. But what about deleting the second item? We use the same syntax:
mySlice = append(mySlice[:1], mySlice[2:]...)
We take all elements from zero index (included) to the first index (not included) and each element from the second index (included) to the end of the array, effectively deleting the value at the second position in the slice (index 1 as we start counting with 0). As you can see, we use the undetermined arguments syntax as the second parameter.
Maps
Maps are like dictionaries--for each word, we have a definition but we can use any type as word or definition and they'll never be ordered alphabetically. We can create maps of string that point to numbers, a string that points to interfaces
and structs
that point to int
and int
to function
. You cannot use as key: slices, the functions, and maps. Finally, you create maps by using the keyword make and specifying the key type and the value type:
myMap := make(map[string]int) myMap["one"] = 1 myMap["two"] = 2 fmt.Println(myMap["one"])
When parsing JSON content, you can also use them to get a string[interface]
map:
myJsonMap := make(map[string]interface{}) jsonData := []byte(`{"hello":"world"}`) err := json.Unmarshal(jsonData, &myJsonMap) if err != nil { panic(err) } fmt.Printf("%s\n", myJsonMap["hello"])
The myJsonMap
variable is a map that will store the contents of JSON and that we will need to pass its pointer to the Unmarshal
function. The jsonData
variable declares an array of bytes with the typical content of a JSON object; we are using this as the mock object. Then, we unmarshal the contents of the JSON storing the result of the memory location of myJsonMap
variable. After checking that the conversion was ok and the JSON byte array didn't have syntax mistakes, we can access the contents of the map in a JSON-like syntax.