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
- From an array:
slice := array[start:end] - From another slice:
newSlice := slice[start:end] - Direct creation:
- Literal:
slice := []int{1, 2, 3} - Using
make:slice := make([]int, length, capacity)
- Literal:
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)
}
}