Arrays and Slices
## Learning Objectives
- Understand arrays and their fixed size
- Master slices with dynamic size
- Use make, append, len, cap
- Slice internals and backing arrays
- Copy and iteration
## Arrays
### Declaration
```go
var nums [5]int // Array of 5 integers, zero-initialized
var ages [3]int = [3]int{20, 25, 30}
prices := [4]float64{9.99, 19.99, 29.99, 39.99}
```
### With Ellipsis
```go
scores := [...]int{95, 85, 78, 92} // Compiler counts elements
fmt.Println(len(scores)) // 4
```
### Array Length
```go
nums := [5]int{1, 2, 3, 4, 5}
fmt.Println(len(nums)) // 5
```
### Access Elements
```go
nums := [5]int{10, 20, 30, 40, 50}
fmt.Println(nums[0]) // 10 (first element)
fmt.Println(nums[4]) // 50 (last element)
nums[2] = 35 // Modify element
```
## Slices
### Slice Declaration
```go
slice := []int{1, 2, 3, 4, 5} // Slice literal
var slice []int // nil slice
emptySlice := []int{} // Empty slice (not nil)
```
### Array to Slice
```go
nums := [5]int{1, 2, 3, 4, 5}
slice := nums[1:4] // Elements at index 1, 2, 3
fmt.Println(slice) // [2 3 4]
// Full slice
all := nums[:] // [1 2 3 4 5]
firstThree := nums[:3] // [1 2 3]
lastTwo := nums[3:] // [4 5]
```
### Slice Syntax
```go
slice[start:end] // start inclusive, end exclusive
slice[start:] // from start to end
slice[:end] // from beginning to end-1
slice[:] // entire slice
```
## make Function
### Create Slice
```go
slice := make([]int, 5) // Slice of 5 ints, zero-initialized
slice := make([]int, 5, 10) // Slice with length 5, capacity 10
```
### Create Map
```go
m := make(map[string]int, 100) // Map with initial capacity
```
### Create Channel
```go
ch := make(chan int, 10) // Buffered channel
```
## len and cap
### Length vs Capacity
```go
slice := make([]int, 3, 10)
fmt.Println(len(slice)) // 3 (number of elements)
fmt.Println(cap(slice)) // 10 (available space)
```
### nil Slice
```go
var slice []int // nil slice
fmt.Println(len(slice)) // 0
fmt.Println(cap(slice)) // 0
```
### Empty Slice
```go
slice := []int{}
fmt.Println(len(slice)) // 0
fmt.Println(cap(slice)) // 0
```
## append Function
### Basic append
```go
slice := []int{1, 2, 3}
slice = append(slice, 4) // [1 2 3 4]
slice = append(slice, 5, 6) // [1 2 3 4 5 6]
```
### Append Another Slice
```go
slice1 := []int{1, 2, 3}
slice2 := []int{4, 5, 6}
slice1 = append(slice1, slice2...) // [1 2 3 4 5 6]
```
### Grow Slice
```go
slice := make([]int, 0, 2) // capacity 2
slice = append(slice, 1) // [1]
slice = append(slice, 2) // [1 2]
slice = append(slice, 3) // [1 2 3] - capacity doubles
```
## Slice Internals
### Structure
A slice has three components:
1. Pointer to underlying array
2. Length (number of elements)
3. Capacity (available space)
```go
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
```
### Backed by Array
```go
array := [5]int{1, 2, 3, 4, 5}
slice := array[1:4] // Points to elements 2, 3, 4
slice[0] = 10 // Modifies underlying array
fmt.Println(array) // [1 10 3 4 5]
```
### Reslice
```go
slice := []int{1, 2, 3, 4, 5}
s := slice[1:3] // [2 3]
s = s[:cap(s)] // Reslice to extend
fmt.Println(s) // [2 3 4 5]
```
## copy Function
### Basic Copy
```go
src := []int{1, 2, 3}
dst := make([]int, len(src))
n := copy(dst, src)
fmt.Println(dst, n) // [1 2 3] 3
```
### Partial Copy
```go
src := []int{1, 2, 3, 4, 5}
dst := make([]int, 2)
n := copy(dst, src)
fmt.Println(dst, n) // [1 2] 2
```
### Overlapping Slices
```go
slice := []int{1, 2, 3, 4, 5}
n := copy(slice[2:], slice[:3])
fmt.Println(slice) // [1 2 1 2 3]
```
## Iteration
### Range Loop
```go
slice := []int{10, 20, 30}
for i, v := range slice {
fmt.Printf("Index: %d, Value: %d\n", i, v)
}
// Index only
for i := range slice {
fmt.Println(i)
}
// Value only
for _, v := range slice {
fmt.Println(v)
}
```
### With Index Variable
```go
slice := []string{"a", "b", "c"}
for i := 0; i < len(slice); i++ {
fmt.Printf("%d: %s\n", i, slice[i])
}
```
## Filtering Slices
### Without Allocation
```go
slice := []int{1, 2, 3, 4, 5, 6}
result := slice[:0]
for _, v := range slice {
if v%2 == 0 {
result = append(result, v)
}
}
fmt.Println(result) // [2 4 6]
```
## Sorting Slices
### Import sort
```go
import "sort"
slice := []int{3, 1, 4, 1, 5, 9}
sort.Ints(slice)
fmt.Println(slice) // [1 1 3 4 5 9]
strings := []string{"banana", "apple", "cherry"}
sort.Strings(strings)
fmt.Println(strings) // [apple banana cherry]
```
### Reverse Sort
```go
slice := []int{3, 1, 4, 1, 5, 9}
sort.Sort(sort.Reverse(sort.IntSlice(slice)))
fmt.Println(slice) // [9 5 4 3 1 1]
```
### Custom Sort
```go
type Person struct {
Name string
Age int
}
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Charlie", 35},
}
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
```
## Common Operations
### Remove Element
```go
slice := []int{1, 2, 3, 4, 5}
i := 2 // Remove element at index 2
slice = append(slice[:i], slice[i+1:]...)
fmt.Println(slice) // [1 2 4 5]
```
### Push/Pop
```go
slice := []int{1, 2, 3}
// Push
slice = append(slice, 4) // [1 2 3 4]
// Pop
last := slice[len(slice)-1]
slice = slice[:len(slice)-1]
fmt.Println(last) // 4
```
### Stack Operations
```go
stack := []int{}
// Push
stack = append(stack, 1)
stack = append(stack, 2)
stack = append(stack, 3)
// Pop
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Println(top) // 3
```
## 2D Slices
### 2D Slice Declaration
```go
matrix := [][]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
for i := range matrix {
for j := range matrix[i] {
fmt.Printf("%d ", matrix[i][j])
}
fmt.Println()
}
```
### Jagged Array
```go
jagged := make([][]int, 3)
for i := range jagged {
jagged[i] = make([]int, i+1)
for j := range jagged[i] {
jagged[i][j] = i*j
}
}
```
## Summary
- Arrays have fixed size, slices are dynamic
- Slices consist of pointer, length, and capacity
- `make()` creates slices with specified length and capacity
- `append()` adds elements, doubling capacity when needed
- Slices reference underlying arrays - modifications affect all slices
- `len()` returns element count, `cap()` returns available space
- `copy()` copies elements between slices
- Use `sort.Ints()`, `sort.Strings()`, `sort.Slice()` for sorting
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →