Skip to main content
โšก Calmops

Go Slices: Dynamic Arrays and Operations

Go Slices: Dynamic Arrays and Operations

Slices are one of Go’s most important data structures. They provide dynamic arrays with flexible sizing and powerful operations.

Slice Basics

Creating Slices

package main

import "fmt"

func main() {
    // Slice literal
    numbers := []int{1, 2, 3, 4, 5}
    fmt.Println(numbers)

    // Make with length
    slice1 := make([]int, 5)
    fmt.Println(slice1)  // [0 0 0 0 0]

    // Make with length and capacity
    slice2 := make([]int, 3, 10)
    fmt.Println(len(slice2), cap(slice2))  // 3 10

    // Slice from array
    arr := [5]int{1, 2, 3, 4, 5}
    slice3 := arr[1:4]
    fmt.Println(slice3)  // [2 3 4]
}

Slice Length and Capacity

package main

import "fmt"

func main() {
    slice := make([]int, 3, 10)

    fmt.Println("Length:", len(slice))      // 3
    fmt.Println("Capacity:", cap(slice))    // 10

    // Append increases length
    slice = append(slice, 1, 2, 3, 4)
    fmt.Println("Length:", len(slice))      // 7
    fmt.Println("Capacity:", cap(slice))    // 10
}

Slice Operations

Appending Elements

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3}

    // Append single element
    slice = append(slice, 4)
    fmt.Println(slice)  // [1 2 3 4]

    // Append multiple elements
    slice = append(slice, 5, 6, 7)
    fmt.Println(slice)  // [1 2 3 4 5 6 7]

    // Append another slice
    other := []int{8, 9}
    slice = append(slice, other...)
    fmt.Println(slice)  // [1 2 3 4 5 6 7 8 9]
}

Slicing Operations

package main

import "fmt"

func main() {
    numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    // Slice from index to index
    fmt.Println(numbers[2:5])    // [3 4 5]

    // Slice from beginning
    fmt.Println(numbers[:3])     // [1 2 3]

    // Slice to end
    fmt.Println(numbers[7:])     // [8 9 10]

    // Full slice
    fmt.Println(numbers[:])      // [1 2 3 4 5 6 7 8 9 10]
}

Copying Slices

package main

import "fmt"

func main() {
    original := []int{1, 2, 3, 4, 5}

    // Shallow copy (reference)
    reference := original
    reference[0] = 999
    fmt.Println(original)   // [999 2 3 4 5]

    // Deep copy
    original2 := []int{1, 2, 3, 4, 5}
    copy := make([]int, len(original2))
    copy(copy, original2)
    copy[0] = 999
    fmt.Println(original2)  // [1 2 3 4 5]
}

Removing Elements

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5}

    // Remove element at index 2
    index := 2
    slice = append(slice[:index], slice[index+1:]...)
    fmt.Println(slice)  // [1 2 4 5]

    // Remove first element
    slice = slice[1:]
    fmt.Println(slice)  // [2 4 5]

    // Remove last element
    slice = slice[:len(slice)-1]
    fmt.Println(slice)  // [2 4]
}

Slice Iteration

Range Iteration

package main

import "fmt"

func main() {
    numbers := []int{10, 20, 30, 40, 50}

    // Iterate with index and value
    for i, v := range numbers {
        fmt.Printf("Index: %d, Value: %d\n", i, v)
    }

    // Iterate with index only
    for i := range numbers {
        fmt.Printf("Index: %d\n", i)
    }

    // Iterate with value only
    for _, v := range numbers {
        fmt.Printf("Value: %d\n", v)
    }
}

Slice Patterns

Filtering Slice

package main

import "fmt"

func filterEven(numbers []int) []int {
    var result []int
    for _, n := range numbers {
        if n%2 == 0 {
            result = append(result, n)
        }
    }
    return result
}

func main() {
    numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    evens := filterEven(numbers)
    fmt.Println(evens)  // [2 4 6 8 10]
}

Mapping Slice

package main

import "fmt"

func double(numbers []int) []int {
    result := make([]int, len(numbers))
    for i, n := range numbers {
        result[i] = n * 2
    }
    return result
}

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    doubled := double(numbers)
    fmt.Println(doubled)  // [2 4 6 8 10]
}

Reducing Slice

package main

import "fmt"

func sum(numbers []int) int {
    total := 0
    for _, n := range numbers {
        total += n
    }
    return total
}

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    total := sum(numbers)
    fmt.Println(total)  // 15
}

Best Practices

โœ… Good: Pre-allocate Slices

// DO: Pre-allocate when size is known
slice := make([]int, 0, 1000)
for i := 0; i < 1000; i++ {
    slice = append(slice, i)
}

โŒ Bad: Repeated Allocation

// DON'T: Repeatedly allocate without capacity
var slice []int
for i := 0; i < 1000; i++ {
    slice = append(slice, i)  // Reallocates frequently
}

โœ… Good: Use Copy for Deep Copy

// DO: Use copy() for deep copying
original := []int{1, 2, 3}
copied := make([]int, len(original))
copy(copied, original)

โœ… Good: Check Bounds

// DO: Check slice bounds
if index >= 0 && index < len(slice) {
    value := slice[index]
}

Summary

Go slices provide:

  1. Dynamic sizing with append
  2. Efficient slicing operations
  3. Range iteration for easy access
  4. Copy semantics for data safety
  5. Powerful patterns for data manipulation

These features make slices essential for Go programming.

Comments