Is it possible to test whether two slices reference the same underlying array?

758 views
Skip to first unread message

Tom Payne

unread,
Mar 29, 2014, 8:36:08 AM3/29/14
to golang-nuts
Hi,

I'm writing some functions that need to do deep clones of slices, and I'd like to test my code to ensure that it creates a new underlying array for each cloned slice.

See:

Is this achievable in Go? I've found that I can use the test:
  unsafe.Pointer(*slice1) != unsafe.Pointer(*slice2)
to test whether to slices are the same (slices can otherwise only be compared to nil), but this still isn't quite right: BadClone in the code passes this test, but the slice it returns still references the same array.

Notes:
- this is for tests only, not for live code, so I don't mind using hacks like the use of unsafe.Pointer above
- the actual slices that I'm testing are deeply nested, up to four levels deep ([][][][]float64 is how GeoJSON represents the coordinates of a MultiPolygon), so I'd like a more generic test than mutating elements of the supposed clone and testing to see if the original array is mutated, if possible.

Thanks!
Tom

Christoph Hack

unread,
Mar 29, 2014, 8:42:03 AM3/29/14
to golan...@googlegroups.com, t...@tompayne.org
The big.math package which uses slices in order to store numbers with arbitrary precision does something similar for performance reasons. They are using the following check:

Jan Mercl

unread,
Mar 29, 2014, 8:46:46 AM3/29/14
to Christoph Hack, golang-nuts, t...@tompayne.org
That works iff the slices in question are guaranteed to _not_ be a
result of a general full slice expression[0]. (Which holds within the
math/big package for the nat type)

[0]: http://golang.org/ref/spec#Slice_expressions

-j

Tom Payne

unread,
Mar 29, 2014, 8:51:05 AM3/29/14
to Christoph Hack, golang-nuts
Many thanks. I tested it here:

As I understand it, this approach works by testing the addresses of corresponding elements in the slice.

However, if this understanding is correct, then that means it only works if the corresponding elements can be identified. What about the following case:

  orig := []int{1, 2, 3, 4}
  slice1 := orig[:2]
  slice2 := orig[2:]

In this case, slice1 and slice2 both reference the same underlying array but have no elements in common. Can the shared referenced array be detected in this case?

Christoph Hack

unread,
Mar 29, 2014, 9:00:46 AM3/29/14
to golan...@googlegroups.com, Christoph Hack, t...@tompayne.org
In this case, slice1 and slice2 both reference the same underlying array but have no elements in common. Can the shared referenced array be detected in this case?

The check works fine for this case. slice1 and slice2 are resized to the capacity of their underlying arrays and then the address of the last element is compared:


-christoph

Tom Payne

unread,
Mar 29, 2014, 9:05:42 AM3/29/14
to Christoph Hack, golang-nuts
Ah, I see. Clever! Now I also understand Jan's comment about full slice expressions.

I don't need full slice expressions in my library, so this approach is perfect for me.

Thanks again Christoph and Jan!
Reply all
Reply to author
Forward
0 new messages