Live data from Hacker News

a[low:high:max] in Golang – A Rare Slice Trick

build-your-own.org

11–20 of 131 posts

Re: a[low:high:max] in Golang – A Rare Slice Trick

#11
post #9

Earlier quoted context omitted.

Go has no way to ensure "const correctness". If you pass around a slice (which you'll be doing a lot, since it's essentially Go's equivalent of a vector), everyone can modify the slice however they please. It's just a fat pointer. So yes, something which should be treated as immutable. The way Go works here easily leads to bugs, especially when concurrency is involved and slices get captured or used by goroutines. If…

But also strings are actually immutable sometimes (at the very least when hardcoded), and they can be converted to a `[]byte` slice that looks mutable, but panics when modified. AFAIK no other slice-like data in Go behaves like this. Fun!

This is a pretty good vignette of how Go is designed. "Users don't need this feature (immutability, polymorphism, etc.), let's not include it. Ah crap, turns out we actually need it for a core language feature. Is there a lesson we can take away here? Nah, just make an ad-hoc implementation of the functionality in this one place."

Re: a[low:high:max] in Golang – A Rare Slice Trick

#12

Earlier quoted context omitted.

There are no immutable arrays. If you have a slice of capacity ten with four elements, you can write a fifth element to it. If you reduce the capacity to four, then a new slice must be allocated to store five elements. The backing store for a slice is just a pointer. The rule is you don't give people pointers that you don't want them to write to.

That's just not true. There are immutable arrays in length. [4]int cannot be appended to. The backing of all slices are array types and array doubling is used for appends that go beyond the capacity. https://go.dev/ref/spec#Array_types

Yeah, that was a mistake.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#13
post #11
post #9

Earlier quoted context omitted.

But also strings are actually immutable sometimes (at the very least when hardcoded), and they can be converted to a `[]byte` slice that looks mutable, but panics when modified. AFAIK no other slice-like data in Go behaves like this. Fun!

This is a pretty good vignette of how Go is designed. "Users don't need this feature (immutability, polymorphism, etc.), let's not include it. Ah crap, turns out we actually need it for a core language feature. Is there a lesson we can take away here? Nah, just make an ad-hoc implementation of the functionality in this one place."

"X for me but not for thee" is very much the vibe Go gives me, yeah.

I mean, I have completely replaced my adhoc Python use with it and I'm much happier. But it's terrifying to use to build large systems.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#14
post #9

Earlier quoted context omitted.

Go has no way to ensure "const correctness". If you pass around a slice (which you'll be doing a lot, since it's essentially Go's equivalent of a vector), everyone can modify the slice however they please. It's just a fat pointer. So yes, something which should be treated as immutable. The way Go works here easily leads to bugs, especially when concurrency is involved and slices get captured or used by goroutines. If…

But also strings are actually immutable sometimes (at the very least when hardcoded), and they can be converted to a `[]byte` slice that looks mutable, but panics when modified. AFAIK no other slice-like data in Go behaves like this. Fun!

I don't think you can convert a string to []byte without unsafe except by copying?

Re: a[low:high:max] in Golang – A Rare Slice Trick

#15
Tangential, but if OP is the owner of the site, could you talk a little bit about your book writing process?

- How you write

- How you render the PDF

- How you develop your plans

That kind of thing. I find it super interesting to self-publish software books and I've been slowly writing one for about a year now. Really curious about this stuff in general and it looks like you've got a solid process down.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#16
post #10
post #3

Earlier quoted context omitted.

I don't know much Go but what does it mean to "accidentally" append to an immutable array? Are there just no particular guards for arrays and they are saying something which should be treated as immutable?

Here's a succinct demonstration: https://go.dev/play/p/Li6_Rpe2R5L Basically: a slice is a triple of {ptr to allocation, number of elements used, size of allocation} the slices will share the same underlying allocation. By specifying the third parameter in the slice function, you set the capacity equal to the number of elements in your slice. This forces the next append to reallocate and copy the contents into a new…

Here another illustration of how slices sometimes alias each other, sometimes not. https://mobile.twitter.com/erikcorry/status/1561635841495236...

Re: a[low:high:max] in Golang – A Rare Slice Trick

#17
post #10

Earlier quoted context omitted.

Here's a succinct demonstration: https://go.dev/play/p/Li6_Rpe2R5L Basically: a slice is a triple of {ptr to allocation, number of elements used, size of allocation} the slices will share the same underlying allocation. By specifying the third parameter in the slice function, you set the capacity equal to the number of elements in your slice. This forces the next append to reallocate and copy the contents into a new…

Here another illustration of how slices sometimes alias each other, sometimes not. https://mobile.twitter.com/erikcorry/status/1561635841495236...

and yet another one (thanks to Erik): https://github.com/tlk/go-wat/blob/41cc21294a953dc7ad07a9b40...

Re: a[low:high:max] in Golang – A Rare Slice Trick

#18
post #3

This paragraph is scary. It looks like a good idea for the Golang version of the Underhanded C Contest. > This trick is useful for returning a slice from an immutable array; if you accidentally append to the supposedly immutable slice, a copy is forced and no data is overwritten because there is no more capacity left.

I don't know much Go but what does it mean to "accidentally" append to an immutable array? Are there just no particular guards for arrays and they are saying something which should be treated as immutable?

Sounds like they're just badly describing copy-on-write.

The original slice uses no extra memory because as long as you treat it as immutable it won't actually make a copy. As soon as you try to modify it, then the copy is made and the extra memory used.

Re: a[low:high:max] in Golang – A Rare Slice Trick

#19
post #18
post #3

Earlier quoted context omitted.

I don't know much Go but what does it mean to "accidentally" append to an immutable array? Are there just no particular guards for arrays and they are saying something which should be treated as immutable?

Sounds like they're just badly describing copy-on-write. The original slice uses no extra memory because as long as you treat it as immutable it won't actually make a copy. As soon as you try to modify it, then the copy is made and the extra memory used.

[deleted]

Re: a[low:high:max] in Golang – A Rare Slice Trick

#20
post #6
post #3

Earlier quoted context omitted.

I don't know much Go but what does it mean to "accidentally" append to an immutable array? Are there just no particular guards for arrays and they are saying something which should be treated as immutable?

Append mutates or copies-and-appends based on the capacity of the slice it's given. And since slicing an array or a slice gives you just a view , not a copy, it can cause "spooky action at a distance" and mutate things you didn't expect, especially if it was a slice with extra capacity of data used somewhere else. Which is what this article is describing. Plus the knowledge of the change in length (to see the appende…

So in other words, appending to a slice may overwrite data in the middle of a different slice?
Post reply on HN