4 Collection Types
Go’s collection types exist to make working with multiple values practical, efficient, and expressive. The chapter introduces arrays, slices, and maps as built-in tools for ordered and key-based data, emphasizing that each fills a different role. Arrays provide fixed-size storage with contiguous memory, slices build on arrays to create flexible dynamic lists, and maps offer fast lookup by key instead of by position. Together, these types let programs model real data more naturally than single variables ever could.
Arrays are presented first as value-based, fixed-length collections whose size is part of the type itself. The chapter explains how arrays are declared, initialized, indexed, copied, and iterated, including multidimensional arrays and arrays of pointers. It also highlights important tradeoffs: arrays are efficient for contiguous storage and can be passed by pointer to avoid expensive copying, but their immutability in length makes them awkward for general-purpose collections. This limitation motivates the move to slices, which preserve array-like indexing while adding dynamic length and capacity.
Slices are shown as the preferred ordered collection in Go because they separate the slice header from the backing array, allowing growth, sub-slicing, copying, and efficient sharing of data. The chapter covers slice creation with literals and make, the behavior of nil and empty slices, how append can allocate new backing storage, and why returning the updated slice is often necessary after growth. It then introduces slice expressions and copy for controlled reuse and duplication, before shifting to maps as unordered key/value collections implemented with hash tables. Maps are demonstrated with declaration, access, deletion, iteration, key existence checks, and use with comparable key types such as strings and structs, reinforcing that maps are the most flexible choice when data is best retrieved by meaning rather than position.
Illustation Of intArray In Listing 4.1 After Declaration And Assignment
The intArray Value, After Declaration
The intArrayShort Value, After Declaration
Array Declared With Only Certain Values
Arrays Declared With Lengths Automatically Calculated
Retrieving And Setting Array Values
An Array Of Pointers That Point To Integers
Array Assignment
Two Arrays Of Pointers Referencing The Same Objects
Two-dimensional Arrays And Their Outer and Inner Values
Assigning An Element Of A Two-Dimensional Array
Values At Different Levels
Passing A Large Array By Value
Slice Internals
Slice Variable Declared And Initialized With A Literal
Slice Initialized With make And A Length
Slice Initialized With A Length And A Larger Capacity
Slice Initialized With Length 0 And A Larger Capacity
A Nil-slice
Append With Allocation Step 1: Allocate New Slice With Storage
Append With Allocation Step 2: Copy Old Values And Assigne New Ones
Append With Allocation Step 3: Return The New Slice To Overwrite The Old One
Append Without Allocation
addOneToAll Modifying The Same Values In Memory
addOneToAll Modifying A New Slice After Append
addOneToAll Appending And Modifying, But New Value Is Inaccessible
Slice Expression Syntax Illustrated
New Slices Created With Slice Expressions
New Slice Created From An Array
New Slices Created With And Without A max Value
Copy Illustrated
Different Zero-length Slices Illustrated
Example Map Illustrated
Relationship Between Keys And Values
Simple Representation Of The Internal Structure Of A Map
Simple Representation Of The Internal Structure Of A Map
Map Declarations Visualized
Summary
- Arrays are constant-sized collections of data that form the basis of the slice and map types.
- Slices are powerful and flexible ordered collection types, and the primary ordered collection type in Go.
-
appendworks by returning a new slice header, though it does not always allocate new storage. - Maps are Go’s associative array or "dictionary" type, and allow you to store values of any type using a key type best suited for your use-case.
- Slices and maps are fundamentally reference types that point to the data they contain, and it helps to be mindful of how they work and when you should modify them.
FAQ
What are the three collection types in Go covered in this chapter?
Go provides arrays, slices, and maps. Arrays are fixed-size ordered collections, slices are dynamic ordered collections built on arrays, and maps store key-value pairs for fast lookup.How is an array different from a slice in Go?
An array has a fixed length that is part of its type, while a slice is a flexible view over an underlying array. Slices can grow or shrink, but arrays cannot change size once declared.Why are arrays considered less flexible than slices?
Arrays cannot expand or shrink after creation, so they are not ideal when the number of items is unknown or changes over time. Slices solve this by providing dynamic length and capacity.What does it mean that array indexes start at 0?
It means the first element in an array is accessed with index0, the second with 1, and so on. This is standard in Go and most C-like languages.How do you create and initialize a slice in Go?
You can use a slice literal like[]int{10, 20, 30} or the make function such as make([]int, 3). A slice literal creates a slice with values, while make allocates a slice with zero values.What is the difference between slice length and capacity?
Length is the number of elements currently in the slice, while capacity is how many elements the underlying array can hold from the slice’s starting point. Capacity affects whetherappend can grow the slice without allocating new storage.What happens when you use append on a slice?
append adds one or more elements and returns a new slice. If the existing capacity is enough, it reuses the same backing array; otherwise, Go allocates a larger array, copies the values, and returns the updated slice.Why can modifying a slice inside a function sometimes affect the caller and sometimes not?
Slices share an underlying array, so changing existing elements inside a function is usually visible to the caller. But if the function usesappend and causes reallocation, the function may end up working on a different backing array unless it returns the new slice.How do slice expressions work?
Slice expressions use the forma[low:high] to create a new slice that refers to part of an existing array or slice. They share storage with the original data, and a three-index form a[low:high:max] can limit capacity.How do maps work in Go, and what should you know about missing keys?
Maps store key-value pairs and provide lookup by key rather than by position. If a key does not exist, Go returns the zero value for the element type; if you need to know whether a key exists, use the two-value assignment form:value, found := m[key].
Go in Action, Second Edition ebook for free