Skip to content

Latest commit

 

History

History
149 lines (105 loc) · 4.21 KB

File metadata and controls

149 lines (105 loc) · 4.21 KB

📚 Go Go Code: Arrays, Slice and Maps

Go provides a small set of built-in data structures that are incredibly powerful when used well. Arrays are fixed-length collections of elements. Slices build on arrays, offering flexible, dynamic-sized views. Maps are key-value stores that enable fast lookups and efficient data organization. Together, these types cover most common use cases — from simple lists to complex indexed data.

Arrays ( Fixed Size )

  • Arrays are value types.
  • Size is part of the type: [3]int is not the same as [4]int.
  • Copying an array creates a new copy of all elements.
var arr [3]int = [3]int{1, 2, 3}
fmt.Println(arr[0]) // 1

Slice

  • Slices are reference types — they point to an underlying array.
  • Slices are dynamic sizing.
  • A slice is a small struct with:
type slice struct {
    ptr *T     // pointer to the first element
    len int    // number of elements
    cap int    // capacity (length of underlying array)
}
s := []int{1, 2, 3} // slice with len=3, cap=3
fmt.Println(s[1])   // 2

append on Slice

When we're adding the values to the Slice that have no predefine with size, we will using append to add value to it. While there's memory behaviour of append when work with it and might be having memory/performance issues.

When you append to a slice, Go checks the capacity:

  1. If there's room in the underlying array (len < cap), it reuses the array.
  2. If there's no room, it:
    1. Allocates a new underlying array, typically with double capacity (but implementation may vary)
    2. Copies existing values to the new array
    3. Returns a new slice backed by that new array
func main() {
    s := []int{1, 2, 3}
    fmt.Println(len(s), cap(s)) // 3 3

    s = append(s, 4)            // triggers new allocation
    fmt.Println(len(s), cap(s)) // 4 6 (capacity may double)
}

Slice Reassignment & Pre-Allocating Slices

Because append might return a new underlying array, you must capture the result:

s := []int{1, 2, 3}
append(s, 4)
fmt.Println(s)    // [1 2 3]

s = append(s, 4) 
fmt.Println(s)    // [1 2 3 4]

Based on this example, you can see if we didn't set the result from the append, it's won't update and also meaning when we're doing append actually underlying it's copies a new set of data over and if there's a large list and we using append it's will causing a lot of the memory allocation also slower performance.

So for the scenario we will do Pre-Allocating Slices instead which come with predefine capacity and avoid repeated allocations:

s := make([]int, 0, 10) // len=0, cap=10

This is ideal when you're building up a large list and want to minimize reallocation.

Sharing Underlying Arrays

Slices created from the same array share data:

a := [5]int{1, 2, 3, 4, 5}
s1 := a[0:3]
s2 := a[1:4]

s1[1] = 100
fmt.Println(s2) // [100 3 4]

Maps

A map is Go's built-in hash table — a powerful data structure that lets you associate keys with values. They're fast, flexible, and a common choice for storing dynamic or lookup-style data. Maps key can be any type that's are comparable string, int etc. but not Slices and for value can be any type.

Maps are also references type which similar with Slice, when you're assign or pass an map, it still refers to the same underlying data.

func update(m map[string]int) {
    m["new"] = 1
}

m := map[string]int{}
update(m)
fmt.Println(m) // map[new:1]

Zero Values of Maps

Zero values of a map is nil, while you can initialize it with make(map[string]string). Without intialize, you will still able to read without issues but when writing it will be panic. Example

var m map[string]int
fmt.Println(m["x"]) // 0

m["x"] = 1          //  panic with assignment to entry in nil map

Syntax of Maps

There's few syntax which allow you to access or modify the maps easier.

  1. Key Access & Check Existance
value, ok := m["apple"]
if ok {
    fmt.Println("Found:", value)
} else {
    fmt.Println("Not found")
}
  1. Deleting Key
delete(m, "banana")
  1. Iterating Over Maps

Map iteration order is randomized for safety (to avoid relying on order).

for key, value := range m {
    fmt.Printf("%s -> %d\n", key, value)
}