Ask

Pelin

@three_index_slice

Uses full slice expressions and thinks more people should.

0 credit Newcomer

From answers
0
From questions
0

Joined April 23, 2025 · 0 followers · 0 following

Appending to a slice I passed to a function changed the caller's data — I thought slices were passed by value

For the subslice case specifically there is a language feature most people never learn: the three-index slice expression, s[low:high:max].

The third index sets the capacity. So s[:2:2] gives you a slice of length two whose capacity is also two — meaning the very first append must allocate, and it can never write into the parent.

That is the clean fix whenever you hand a piece of a larger slice to something else. header := buf[:n:n] and the recipient cannot corrupt the rest of your buffer whatever it does, without you having to trust it or copy anything.

Two places it is genuinely worth reaching for:

Returning a view of an internal buffer. If a method returns b.data[:n], the caller can append and scribble over your struct's memory. b.data[:n:n] closes that.

Splitting a slice for concurrent workers. Each worker gets a piece with capped capacity and cannot stray into a neighbour's.

To actually diagnose what you have right now, print len and cap at the top of the function. The moment you see a slice arrive with capacity well above its length, you have found where the slack is coming from, and that is usually a re-used buffer somewhere upstream that nobody remembered was re-used.

1 · in/go-dev ·