|
I think slices are wonderfully intuitive... if you've worked with C. Slices encapsulate an ubiquitous C pattern, where you pass to a function: a pointer (to an initial array element), and a length or capacity (sometimes both). This pattern is directly encapsulated by Go's slices, which can be thought of as something like: type Slice struct {
Ptr *Elem
Len int
Cap int
}
I love Go's slice syntax. It's the right piece of syntactic sugar. It removes tedium and room-for-mistakes from this prevalent C pattern. It lets me work as precisely with memory as I do in C, yet everything is simpler, lighter, and breezier.For example, I'm making a game in Go. I don't want to be allocating memory throughout the game (which can cause frame drops), so instead I allocate giant arrays of memory on launch. Then I use slices to partition this memory as needed. Some of these arrays get their elements re-accumulated at some interval (every level, or every frame, etc.). And so it works nicely to first set them to zero length: myMem = myMem[:0]
Notice that the myMem slice now has zero length, but still points to its same underlying array. Then I perform the accumulation: for ... {
myMem = append(myMem, elem)
}
Again, I don't want to be allocating in general, so I care very much that append continues to use myMem's preexisting capacity.All this is to say, I don't see slices as being the way they are for the "sake of optimization." Rather I see them as an ideal tool for working with, referring to, and partitioning memory. |