Golang DSA Chapter 2 Part 1: Go Basics for Data Structures
Welcome to Chapter 2 of our walkthrough of “Learn Data Structures and Algorithms with Golang” by Bhagvan Kommadi. This is Part 1, where we cover the Go-specific building blocks you need before getting into the heavier data structure topics. Think of this as your toolkit chapter.
Chapter 1 was about what data structures are and how to think about algorithm performance. Now we actually start writing Go code. The book covers arrays, slices, two-dimensional slices, and maps here, and that’s exactly what we’ll walk through.
Arrays: The Simple Starting Point
If you’ve used any programming language before, arrays should feel familiar. An array in Go is a fixed-size collection of elements that all share the same type. Here’s how you declare one:
var arr = [5]int{1, 2, 4, 5, 6}
That gives you an array of 5 integers. Nothing fancy. You can loop through it with a regular for loop:
var i int
for i = 0; i < len(arr); i++ {
fmt.Println("printing elements", arr[i])
}
Or you can use the range keyword, which gives you both the index and the value:
var value int
for i, value = range arr {
fmt.Println("range", value)
}
If you don’t need the index, use the blank identifier _ to ignore it:
for _, value = range arr {
fmt.Println("blank range", value)
}
Here’s the important thing about Go arrays: they are fixed-size. You can’t add more elements than what you declared. If you need a bigger array, you have to create a new one and copy everything over. Also, when you pass an array to a function, Go copies the entire thing. So if you have a huge array, that’s a performance hit.
This is exactly why slices exist.
Slices: Arrays That Can Grow
A slice is basically an array that knows how to resize itself. It sits on top of a regular array but adds the ability to grow when you need more room. When you append elements and the slice runs out of capacity, Go creates a new underlying array (usually double the size) and moves everything over.
Creating a slice looks almost like creating an array, just without the size:
var slice = []int{1, 3, 5, 6}
You can check the length and capacity:
slice = append(slice, 8)
fmt.Println("Capacity", cap(slice))
fmt.Println("Length", len(slice))
The len() function tells you how many elements are in the slice right now. The cap() function tells you how many elements the underlying array can hold before it needs to grow again.
Passing Slices to Functions
Here’s something nice about slices compared to arrays. When you pass a slice to a function, Go passes a reference, not a copy. So modifying the slice inside the function changes the original. No performance penalty for big slices.
func twiceValue(slice []int) {
var i int
var value int
for i, value = range slice {
slice[i] = 2 * value
}
}
func main() {
var slice = []int{1, 3, 5, 6}
twiceValue(slice)
var i int
for i = 0; i < len(slice); i++ {
fmt.Println("new slice value", slice[i])
}
}
After calling twiceValue, your original slice has 2, 6, 10, 12 in it. The function modified it in place because slices are passed by reference.
Two-Dimensional Slices
Sometimes you need a grid, like a chessboard or a matrix. Go handles this with two-dimensional arrays and slices.
A fixed two-dimensional array looks like this:
func main() {
var TwoDArray [8][8]int
TwoDArray[3][6] = 18
TwoDArray[7][4] = 3
fmt.Println(TwoDArray)
}
That gives you an 8x8 grid of integers, all initialized to zero except the two spots you set. It works, but it’s rigid. You can’t resize it.
For something dynamic, you use a slice of slices:
func main() {
var rows int
var cols int
rows = 7
cols = 9
var twodslices = make([][]int, rows)
var i int
for i = range twodslices {
twodslices[i] = make([]int, cols)
}
fmt.Println(twodslices)
}
The make function creates a slice with the specified number of rows, and then you loop through each row to create the columns. Now you have a 7x9 grid that you built dynamically.
Sub-Slicing and Appending
You can also grab pieces of an existing slice and work with them:
var arr = []int{5, 6, 7, 8, 9}
var slic1 = arr[:3]
fmt.Println("slice1", slic1) // [5 6 7]
var slic2 = arr[1:5]
fmt.Println("slice2", slic2) // [6 7 8 9]
var slic3 = append(slic2, 12)
fmt.Println("slice3", slic3) // [6 7 8 9 12]
The arr[:3] syntax grabs elements from index 0 up to (but not including) index 3. The arr[1:5] grabs from index 1 to 4. And append tacks a new element on the end. If the underlying array is full, Go allocates a bigger one behind the scenes.
Maps: Key-Value Pairs
Maps let you store data as key-value pairs. If you’ve used dictionaries in Python or objects in JavaScript, same idea.
Here’s a map with integer keys and string values:
var languages = map[int]string{
3: "English",
4: "French",
5: "Spanish",
}
You can also create maps with make:
var products = make(map[int]string)
products[1] = "chair"
products[2] = "table"
Looping through a map uses range just like slices:
var i int
var value string
for i, value = range languages {
fmt.Println("language", i, ":", value)
}
To get a value by key:
fmt.Println(products[2]) // "table"
To delete an entry:
delete(products, 1)
fmt.Println("products", products)
One thing to keep in mind: map iteration order in Go is not guaranteed. If you loop through the same map twice, you might get the keys in a different order each time. That’s by design.
What We Covered
This first half of Chapter 2 gives you the basic Go data types you’ll use throughout the rest of the book:
- Arrays for fixed-size collections (passed by value, so watch the performance)
- Slices for dynamic collections (passed by reference, can grow as needed)
- Two-dimensional slices for grids and matrices
- Maps for key-value lookups
These are the primitives that everything else builds on. Linked lists, trees, hash tables, they all use some combination of these under the hood.
In Part 2, we’ll look at the rest of Chapter 2, which covers database operations, variadic functions, and CRUD web forms in Go. It gets more practical and shows how these data structures show up in real applications.
This post is part of a series retelling “Learn Data Structures and Algorithms with Golang” by Bhagvan Kommadi (Packt, 2019, ISBN: 978-1-78961-850-1). You can find all posts in the series introduction.
| Navigation | Link |
|---|---|
| Previous | Chapter 1 Part 2: Algorithms and Performance |
| Next | Chapter 2 Part 2: Slices, Maps, and Go Patterns |