Hacker News new | past | comments | ask | show | jobs | submit login

I have found this to be true of everything other than byte slices, where the result is some of the worst bugs I've had the displeasure of tracking down.

Many Go libraries like to offer passing a byte slice to reuse as a destination. Many Go libraries take byte slices or structs containing them as arguments. A common result is "loop over some input, read it into the reusable slice, pass the slice to the next step". It even sort of works - until the next step does something asynchronous.

It doesn't help that:

- Lots of things return a new slice "sometimes" - _this_ append() result is safe to pass on; this other one is not; this other one "it depends".

- The `x[:]` idiom to turn an array into a slice looks exactly like a Python copy, but actually shares the same backing store.

In the end we basically banned reusing slices as a result. (The rule I tell new programmers is "if you pass the slice elsewhere in a loop, the slice needs to be allocated within the loop.") Which is a shame, because the performance gain from safe reuse is often significant. But until the type system blocks us from changes, usually in the oblivious callee, which turn a safe use into an unsafe one, it's simply too much effort to remember and review each case.




In Python's Numpy library, `x[:]` also shares the same backing store. This bit me in the ass when I was learning Numpy.


Ouch. I guess this would be a reason to use strings more, since they're immutable.


Someone using a string when they really want a byte array/slice would fail review on its face. Excepting external APIs forcing "strings" on us, we only use the Go string type for UTF-8 code unit sequences (and this is a common assumption in the Go world).


Using string doesn't allow reuse, so you are leaving significant performance on the table.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: