Comment

Comment by zellyn

The most important thing to know is that Go slices are exactly how you would implement a dynamically growable slice in C if I asked you to. No less, but importantly, no more: a pointer to a piece of memory, and a current length and capacity.

The classic slice mistake is to forget that append doesn't necessarily return a completely new slice backed by a disjoint piece of memory, especially easy if you've been using a language where variables are immutable by default.

The problem is that it will often accidentally work; if you over-run the backing store, you will get a new piece of memory:

    a := make([]int, 1, 1) // a is backed by a one-element-long piece of memory
    a[0] = 42
    b := append(a, 17) // this must allocate a new piece of memory
    c := append(a, 37) // this must also allocate a new piece of memory

    // At this point a == [42], b == [42, 17], c == [42, 37]
The problem is when the existing capacity is sufficient:

    a := make([]int, 1, 10) // a is backed by a ten-element-long piece of memory
    a[0] = 42
    b := append(a, 17) // no need to allocate: just use the existing memory
    c := append(a, 37) // no need to allocate: just (re)use the existing memory

    // At this point a == [42], b == [42, 37], c == [42, 37]
    //                          ^^^^^^^^^^^^^
parent zellyn 1 year ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton