logoalt Hacker News

kbolino • yesterday at 4:46 PM • 1 reply • view on HN

Java arrays are thin pointers to Array objects, which contain the length and data in the same place (on the far side of the pointer). Since thin pointers cannot tear and Array objects cannot be resized, Arrays themselves are always memory-safe in safe code.

Go slices are fat pointers to undecorated memory. The slice itself is a 3-tuple of pointer, length, and capacity. If you append to a slice that's already at capacity, the Go runtime will allocate new memory for you and return a new 3-tuple. If you assign that result to a variable that's also being accessed by another goroutine, the latter can observe the slice in an inconsistent state. It can, for example, see the old pointer but with the new length, allowing out-of-bounds access. None of this requires unsafe code.

The same issue applies to string and interface variables, which are also fat pointers.


Replies

shikck200 • yesterday at 5:00 PM

Indeed.

Shared Go slices are a bad mix in concurrent code. This is a given. But its also not a fair comparison, you should instead compare java arrays to go arrays, not slices.

This goes for slices, strings and maps. Those a usually wrapped in a mutex, or used with sync primitives like sync.Map.

➕ show 2 replies