Daily Tech Brief

Top startup stories in your inbox

Subscribe Free

© 2026 rakrisi Daily

Slices - Dynamic Arrays in Go

Slices: Arrays That Can Grow!

Welcome back! Arrays are great, but they have one big problem: they can’t grow. Once you create an array with 5 boxes, you can never have 6 boxes.

Enter Slices! Slices are like magical arrays that can grow and shrink as needed. Think of them as expandable shopping bags instead of fixed-size boxes.

Arrays vs Slices (Real Life Analogy)

Fixed Array = Fixed Parking Lot

  • Exactly 10 parking spaces
  • Can’t add more spaces
  • Can’t remove spaces
  • Perfect for when you know exactly how many cars you have

Slice = Expandable Backpack

  • Starts with some space
  • Automatically grows when you add more items
  • Can shrink when you remove items
  • Perfect for shopping lists that change

What is a Slice?

A slice is like a window into an array. It shows you only part of the array, but you can move and resize that window.

Think of it like this:

  • Array = A long shelf of books
  • Slice = A bookmark that shows you “books 3 through 7”

Creating Slices

Method 1: From an Array (Like Cutting a Cake)

// Start with a full cake (array)
fullCake := [8]string{"🍰", "🍰", "🍰", "🍰", "🍰", "🍰", "🍰", "🍰"}

// Take a slice (piece) of the cake
middlePiece := fullCake[2:6]  // Pieces 2, 3, 4, 5 (4 pieces)

// Take the first half
firstHalf := fullCake[:4]     // Pieces 0, 1, 2, 3

// Take the second half
secondHalf := fullCake[4:]    // Pieces 4, 5, 6, 7

// Take everything
wholeCake := fullCake[:]      // All pieces

Real Life Example:

// Your weekly schedule
week := [7]string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}

// Work days only
workDays := week[:5]    // ["Mon", "Tue", "Wed", "Thu", "Fri"]

// Weekend only
weekend := week[5:]     // ["Sat", "Sun"]

Method 2: Creating Empty Slices (Empty Shopping Bag)

// Empty slice that can hold strings
var shoppingList []string

// Empty slice with initial space (bag with some pockets)
var todoList = make([]string, 0, 10)  // Can hold up to 10 items initially

// Slice with starting items
fruits := []string{"apple", "banana"}  // Starts with 2 items

Adding Items to Slices (The Magic!)

Using append() - Like Adding to Your Shopping Bag

// Start with empty shopping list
var shopping []string

// Add items one by one
shopping = append(shopping, "milk")
shopping = append(shopping, "bread")
shopping = append(shopping, "eggs")

// Now shopping = ["milk", "bread", "eggs"]

// Add multiple items at once
shopping = append(shopping, "apples", "oranges", "bananas")
// Now shopping = ["milk", "bread", "eggs", "apples", "oranges", "bananas"]

Important: Always use shopping = append(shopping, "item") because append returns a new slice!

Real Life Example: Building a Playlist

package main

import "fmt"

func main() {
    // Start with empty playlist
    var playlist []string
    
    fmt.Println("=== Building My Playlist ===")
    
    // Add songs one by one
    playlist = append(playlist, "Song 1")
    fmt.Printf("Added: %v\n", playlist)
    
    playlist = append(playlist, "Song 2")
    fmt.Printf("Added: %v\n", playlist)
    
    playlist = append(playlist, "Song 3", "Song 4")
    fmt.Printf("Added more: %v\n", playlist)
    
    fmt.Printf("Total songs: %d\n", len(playlist))
}

Output:

=== Building My Playlist ===
Added: [Song 1]
Added: [Song 1 Song 2]
Added more: [Song 1 Song 2 Song 3 Song 4]
Total songs: 4

Understanding Length vs Capacity

Slices have two important measurements:

Length = How many items you have

Capacity = How much space you have

// Create a slice with space for 10 items, but start with 0 items
var numbers = make([]int, 0, 10)

fmt.Printf("Length: %d, Capacity: %d\n", len(numbers), cap(numbers))
// Length: 0, Capacity: 10

// Add 3 numbers
numbers = append(numbers, 1, 2, 3)
fmt.Printf("Length: %d, Capacity: %d\n", len(numbers), cap(numbers))
// Length: 3, Capacity: 10

Think of it like:

  • Length = How many seats are occupied in a theater
  • Capacity = Total seats available in the theater

Reading from Slices

Accessing Items (Same as Arrays)

fruits := []string{"apple", "banana", "orange", "grape"}

first := fruits[0]    // "apple"
second := fruits[1]   // "banana"
last := fruits[3]     // "grape"

Looping Through Slices

scores := []int{85, 92, 78, 90, 88}

fmt.Println("=== All Scores ===")
for i, score := range scores {
    fmt.Printf("Test %d: %d points\n", i+1, score)
}

Modifying Slices

Changing Items

colors := []string{"red", "blue", "green"}

// Change blue to purple
colors[1] = "purple"

// Now colors = ["red", "purple", "green"]

Real Life Example: Updating a To-Do List

package main

import "fmt"

func main() {
    // Start with tasks
    tasks := []string{"buy milk", "clean room", "do homework"}
    
    fmt.Println("Original tasks:", tasks)
    
    // Update a task
    tasks[1] = "clean kitchen"
    
    // Add new tasks
    tasks = append(tasks, "call mom", "exercise")
    
    fmt.Println("Updated tasks:", tasks)
    fmt.Printf("Total tasks: %d\n", len(tasks))
}

Copying Slices

Making a Copy (Like Photocopying a List)

original := []int{1, 2, 3, 4, 5}

// Method 1: Create destination first
copy1 := make([]int, len(original))
copy(copy1, original)

// Method 2: Use append (creates a copy)
copy2 := append([]int(nil), original...)

// Method 3: Slice notation (shares memory!)
copy3 := original[:]  // This shares the same underlying array!

Warning: copy3 := original[:] shares the same memory. If you change copy3, original changes too!

Common Slice Operations

Removing Items

func removeItem(slice []string, index int) []string {
    // Remove item at index by combining parts before and after
    return append(slice[:index], slice[index+1:]...)
}

// Example
fruits := []string{"apple", "banana", "orange", "grape"}
fruits = removeItem(fruits, 1)  // Remove "banana"
// Now fruits = ["apple", "orange", "grape"]

Inserting Items

func insertItem(slice []string, index int, item string) []string {
    // Make space at index
    slice = append(slice[:index+1], slice[index:]...)
    // Put item in the space
    slice[index] = item
    return slice
}

// Example
colors := []string{"red", "blue", "green"}
colors = insertItem(colors, 1, "yellow")
// Now colors = ["red", "yellow", "blue", "green"]

Finding Items

func findItem(slice []string, target string) int {
    for i, item := range slice {
        if item == target {
            return i  // Found at this position
        }
    }
    return -1  // Not found
}

// Example
fruits := []string{"apple", "banana", "orange"}
bananaPos := findItem(fruits, "banana")  // Returns 1
grapePos := findItem(fruits, "grape")    // Returns -1

Real Life Example: Shopping Cart

package main

import "fmt"

func main() {
    // Start with empty cart
    var cart []string
    
    // Add items
    cart = append(cart, "bread", "milk", "eggs")
    fmt.Println("Initial cart:", cart)
    
    // Add more items
    cart = append(cart, "apples", "bananas")
    fmt.Println("Added fruits:", cart)
    
    // Check if we have milk
    hasMilk := false
    for _, item := range cart {
        if item == "milk" {
            hasMilk = true
            break
        }
    }
    
    if hasMilk {
        fmt.Println("✓ You have milk!")
    }
    
    // Remove eggs (let's say we don't need them)
    for i, item := range cart {
        if item == "eggs" {
            cart = append(cart[:i], cart[i+1:]...)
            break
        }
    }
    
    fmt.Println("Final cart:", cart)
    fmt.Printf("Total items: %d\n", len(cart))
}

Output:

Initial cart: [bread milk eggs]
Added fruits: [bread milk eggs apples bananas]
✓ You have milk!
Final cart: [bread milk apples bananas]
Total items: 4

Slice Gotchas (Watch Out!)

The Reference Problem

original := []string{"a", "b", "c"}
copy := original[:]  // This shares memory!

copy[0] = "z"        // This changes BOTH slices!

fmt.Println("Original:", original)  // ["z", "b", "c"] - Changed!
fmt.Println("Copy:", copy)          // ["z", "b", "c"]

Solution: Use copy() function or append() to make real copies.

Capacity Confusion

slice := make([]int, 3, 10)  // Length 3, Capacity 10
slice = append(slice, 1)     // Length becomes 4, still capacity 10

// But if you add 8 more items...
for i := 0; i < 8; i++ {
    slice = append(slice, i)
}
// Now Go might create a new underlying array with more capacity

Practice Time!

Exercise 1: Grade Book

Create a slice to store student grades. Add grades, calculate average, find highest grade.

Exercise 2: To-Do List App

Create functions to:

  • Add tasks
  • Remove completed tasks
  • Find a specific task
  • Show all tasks

Exercise 3: Shopping List

Create a shopping list where you can:

  • Add items
  • Remove items you don’t need
  • Check if an item is already in the list

Key Takeaways

  1. Slices can grow: Use append() to add items
  2. Length vs Capacity: Length is items you have, capacity is space available
  3. Always assign append result: slice = append(slice, item)
  4. Watch for references: Some operations share memory
  5. Use make() for control: make([]Type, length, capacity)

What’s Next?

Slices are incredibly powerful! They form the basis for most data structures in Go. Next, we’ll learn about Strings - how text works in programming!

Quick Quiz

  1. What’s the difference between an array and a slice?
  2. What does append() return?
  3. What’s the difference between length and capacity?
  4. How do you copy a slice safely?
  5. Why do we use slice = append(slice, item) instead of just append(slice, item)?

Remember: Slices are like expandable backpacks. Perfect when you don’t know how many items you’ll need!