Skip to content

Chapter 2 of 7

Composite Types and Data Structures

Slices are the most common composite type in Go. A slice is a flexible, dynamically sized view into an underlying array, and its declaration []int{1, 2, 3} creates one with both length and capacity set. The built-in append adds elements, growing the slice when needed by allocating a new backing array; the runtime typically doubles small slices and grows larger ones by roughly 25% to amortize the cost of repeated reallocation. Two descriptors govern a slice: len(s) reports the number of accessible elements, and cap(s) reports how many elements fit before the next growth. There is a subtle but important distinction between a nil slice (var s []int) and an empty slice (s := []int{} or make([]int, 0)): most operations behave identically, but json.Marshal renders the first as null and the second as []. Assignment between slices shares the underlying array, so changes are visible across both names, while copy(dst, src) duplicates elements into independent storage up to min(len(dst), len(src)). Two-dimensional data is built by composing slices of slices, since Go does not have dynamic multidimensional arrays.

Maps are unordered key-value collections created with make(map[K]V) or with composite literals. Reading a missing key returns the zero value of the value type rather than panicking, but the comma-ok idiom v, ok := m["key"] distinguishes a present-but-zero entry from a missing one. The built-in delete(m, "key") removes an entry (or does nothing if the key is absent), and it is safe to call during iteration. Map elements are not addressable, so &m["key"] is a compile-time error and updates must be done with a plain assignment. Iteration order is intentionally randomized to discourage reliance on it; if deterministic output is required, sort the keys first. Maps are not safe for concurrent use, so access from multiple goroutines requires a mutex or a channel-based protocol.

Structs group related fields under a named type, and Go encourages composition over inheritance through struct embedding. Embedding a type anonymously promotes its fields and methods to the outer struct, so Dog{Animal{Name: "Rex"}, "Labrador"} lets callers write d.Name directly. This is a powerful alternative to classical inheritance and keeps the type hierarchy flat. Arrays, by contrast, have a fixed size baked into their type ([3]int versus [4]int are different types), so slices are overwhelmingly more common in idiomatic Go; a slice can be obtained from an array with the slice expression arr[1:3]. Sorting is handled by the sort package and, since Go 1.21, the slices package: sort.Ints covers built-in numeric types, sort.Slice accepts a custom less function (but is not stable), and sort.SliceStable preserves the relative order of equal elements. The strings package complements these collections with utilities like strings.Builder for efficient concatenation, strings.Repeat for repeated copies, and strings.SplitN for splitting into at most N substrings.

All chapters
  1. 1Language Fundamentals and Project Structure
  2. 2Composite Types and Data Structures
  3. 3Functions, Methods, and Interfaces
  4. 4Error Handling, defer, and Formatting
  5. 5Concurrency
  6. 6Standard Library: I/O, Encoding, Web, and Time
  7. 7Testing, Tooling, and Runtime Internals

Drill it

Reading is not remembering. These come from the Go Programming deck:

Q

What is Go (Golang)?

Go is an open-source programming language developed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. It is statically typed, compiled, and designed fo...

Q

How do you declare a variable in Go?

You can declare variables using:var x int = 10var y = "hello" (type inferred)z := 42 (short declaration, only inside functions)

Q

What is a goroutine?

A goroutine is a lightweight thread managed by the Go runtime. You start one with the go keyword:go myFunction()Goroutines are multiplexed onto OS threads and a...

Q

How do you create a channel in Go?

Use the make function:ch := make(chan int) — unbufferedch := make(chan string, 5) — buffered with capacity 5Channels are used to communicate between goroutines...