Understanding Arrays, Slices, and Maps in Go

Arrays

An array is a fixed-length sequence of elements of the same type, stored contiguously in memory.

Declaration

Declare an array by specifying its length and element type.

var colors [3]string

The length is part of the array's type; [3]int and [5]int are distinct types.

Initialization

Initialize an array during declaration.

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

The compiler can enfer the length using ....

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

Iteration

Access elements via zero-based indices using a for loop with range.

package main
import "fmt"
func main() {
    colors := [...]string{"red", "green", "blue"}
    for idx, val := range colors {
        fmt.Printf("Index %d: %s\n", idx, val)
    }
}

Slices

A slice is a flexible, dynamic view into an underlying array. It consists of a pointer, length, and capacity.

  • Pointer: Address of the first slice element in the underlying array.
  • Length: Number of elements currently in the slice (len()).
  • Capacity: Maximum number of elements from the slice start to the end of the underlying array (cap()).

Creation Methods

  1. From an array: slice := array[start:end]
  2. From another slice: newSlice := slice[start:end]
  3. Direct creation:
    • Literal: slice := []int{1, 2, 3}
    • Using make: slice := make([]int, length, capacity)

Example: Creating from an array

package main
import "fmt"
func main() {
    arr := [5]int{10, 20, 30, 40, 50}
    slc := arr[1:4] // Elements at indices 1, 2, 3
    fmt.Println("Slice:", slc) // [20 30 40]
    fmt.Println("Length:", len(slc)) // 3
    fmt.Println("Capacity:", cap(slc)) // 4
}

Adding Elements

Use the append function to add elements. If capacity is insufficient, a new underlying array is allocated (typically doubling capacity).

package main
import "fmt"
func main() {
    nums := make([]int, 0, 2)
    for i := 0; i < 5; i++ {
        nums = append(nums, i)
        fmt.Printf("Len: %d, Cap: %d\n", len(nums), cap(nums))
    }
}

Removing Elements

Go lacks a built-in delete function for slices. Use append with slicing.

package main
import "fmt"
func main() {
    data := []int{1, 2, 3, 4, 5}
    // Remove element at index 2
    data = append(data[:2], data[3:]...)
    fmt.Println(data) // [1 2 4 5]
    // Remove first element
    data = data[1:]
    fmt.Println(data) // [2 4 5]
    // Remove last element
    data = data[:len(data)-1]
    fmt.Println(data) // [2 4]
}

Iteration

Iterate using for with range.

package main
import "fmt"
func main() {
    items := []string{"a", "b", "c"}
    for i, v := range items {
        fmt.Printf("Pos %d: %s\n", i, v)
    }
}

Maps

A map is an unordered collection of key-value pairs. Keys must be unique and comparable.

Declaration and Initialization

Declare with map[KeyType]ValueType.

var scoreMap map[string]int

Initialize using a literal or make.

// Literal
scoreMap := map[string]int{
    "Alice": 95,
    "Bob": 87,
}
// Using make
scoreMap := make(map[string]int, 10) // Initial capacity hint

Operations

  • Insert/Update: map[key] = value
  • Retrieve: value := map[key]
  • Delete: delete(map, key)
  • Check existence: value, ok := map[key]

Example

package main
import "fmt"
func main() {
    inventory := make(map[string]int)
    inventory["apple"] = 50
    inventory["banana"] = 30
    fmt.Println(inventory)
    qty, exists := inventory["apple"]
    fmt.Printf("Qty: %d, Exists: %v\n", qty, exists)
    delete(inventory, "banana")
    fmt.Println(inventory)
}

Iteration

Iteration order is non-detemrinistic.

package main
import "fmt"
func main() {
    codes := map[string]int{"US": 1, "UK": 44, "DE": 49}
    for country, code := range codes {
        fmt.Printf("%s: +%d\n", country, code)
    }
}

Concurrent Access

Standard maps are not goroutine-safe. Use synchronization.

Using a Mutex

package main
import (
    "fmt"
    "sync"
)
var mu sync.RWMutex
func main() {
    sharedMap := make(map[int]string)
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(idx int) {
            defer wg.Done()
            mu.Lock()
            sharedMap[idx] = fmt.Sprintf("Value%d", idx)
            mu.Unlock()
        }(i)
    }
    wg.Wait()
    fmt.Println(sharedMap)
}

Using sync.Map sync.Map is optimized for concurrent use.

package main
import (
    "fmt"
    "sync"
)
func main() {
    var concurrentMap sync.Map
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(idx int) {
            defer wg.Done()
            concurrentMap.Store(idx, idx*10)
        }(i)
    }
    wg.Wait()
    concurrentMap.Range(func(k, v interface{}) bool {
        fmt.Printf("Key: %v, Value: %v\n", k, v)
        return true
    })
}

The range Keyword

range iterates over elements of arrays, slices, strings, maps, and channels.

Examples

package main
import "fmt"
func main() {
    // Slice
    for i, v := range []int{5, 10, 15} {
        fmt.Println(i, v)
    }
    // Map
    for k, v := range map[string]int{"x": 1, "y": 2} {
        fmt.Println(k, v)
    }
    // String (iterates over runes)
    for i, r := range "Go" {
        fmt.Printf("%d -> %c\n", i, r)
    }
}

Tags: Go Golang Arrays slices maps

Posted on Wed, 13 May 2026 17:56:36 +0000 by d3vilr3d