Reducing slice capacity?

1,559 views
Skip to first unread message

Glenn Brown

unread,
Oct 26, 2012, 9:26:45 PM10/26/12
to golan...@googlegroups.com, Glenn Brown
When reslicing, is there any way to force the new slice to have cap(newSlice) == len(newSlice) without using copy?

I ask because if I have
original := make([]int, 10)
then
Window := original[5:]
cap(Window) == 5
but
Dangerous := original[:5]
cap(Dangerous) == 10
. That is, Window cannot be used to modify the original buffer outside the bounds of the reslice, but Dangerous can.
So, Window is sort of a runtime-enforced window into the original buffer, but Dangerous is not.

Thanks,
--Glenn




Maxim Khitrov

unread,
Oct 26, 2012, 9:47:23 PM10/26/12
to Glenn Brown, golan...@googlegroups.com
You can do this with unsafe, but I don't know what the exact implications are:

http://play.golang.org/p/4nd7NnqXHy

Would the GC be ok with this?

- Max

DisposaBoy

unread,
Oct 26, 2012, 10:55:23 PM10/26/12
to golan...@googlegroups.com, Glenn Brown
I think the question has already been answered so I'll just ask.. Why are you so afraid of copy?


 

Peter S

unread,
Oct 26, 2012, 10:55:41 PM10/26/12
to Glenn Brown, golan...@googlegroups.com
There is a request for adding new syntax to allow this, but I don't know if there are plans for implementing it:

https://code.google.com/p/go/issues/detail?id=1642

Peter






--



Glenn Brown

unread,
Oct 27, 2012, 12:15:27 AM10/27/12
to DisposaBoy, Glenn Brown, golan...@googlegroups.com
> I think the question has already been answered so I'll just ask.. Why are you so afraid of copy?

Copies don't have the same semantics, and aren't free when large. But mainly I'm just trying to understand if I can program more defensively when passing slices to third parties.

--Glenn

Uli Kunitz

unread,
Oct 27, 2012, 5:22:41 AM10/27/12
to golan...@googlegroups.com, Glenn Brown
Both slices are dangerous because the can change the original. If you want to prevent any change on the original slice you will need to create a copy.

Carlos Castillo

unread,
Oct 29, 2012, 2:09:17 AM10/29/12
to golan...@googlegroups.com, Glenn Brown
Modifying the capacity of a slice won't prevent someone from using unsafe to read the memory outside the region you've given them, but it does prevent accidents within "safe" go code (poor use of append + the like) from messing up your data, and makes errors in other's code more obvious.

Ignoring malicious/unsafe code, where the best way to protect your data is to make copies, by adjusting the capacity of a slice you can avoid problems like: http://play.golang.org/p/WjkNlKM1mi

I have created two functions to do what you're looking for in https://github.com/cookieo9/go-misc/blob/master/slice/cap.go

The first "ShrinkCapacity()", takes an array pointer and allows you to shrink (but not grow) the cap value *in-place*. The second "HardSlice" performs a regular slice operation, but after completing sets cap to len so the resulting slice can't be expanded into by append. Both functions are generic in that they can (by using reflection) take any type of slice, but bad input will result in runtime panics instead of compile-time errors, and they will have slightly worse performance than a built-in solution or writing your own unsafe code.

eg:


base := make([]int, 10)

// Faster (less reflection)
a := base[:5]
slice.ShrinkCapacity(&a,len(a))

// One-Line but with annoying type assertion
b := slice.HardSlice(base,5,10).([]int)
Reply all
Reply to author
Forward
0 new messages