is this safe?

269 views
Skip to first unread message

Trig

unread,
Nov 20, 2017, 11:48:31 AM11/20/17
to golang-nuts
for i, user := range myList {
 
if user.Disabled {
  myList
= append(myList[:i], myList[i + 1:]...) // remove user from return list
 
}
}


Is using append this way (to remove an index), inside of the range loop of the same array I'm working with, safe... since the size of myList is being changed within it?

Jan Mercl

unread,
Nov 20, 2017, 12:32:34 PM11/20/17
to Trig, golang-nuts
On Mon, Nov 20, 2017 at 5:48 PM Trig <edb...@gmail.com> wrote:

> Is using append this way (to remove an index), inside of the range loop of the same array I'm working with, safe... since the size of myList is being changed within it? 

It's safe as it will not crash your program. It's unsafe as it's a quadratic algorithm instead of a linear one.

--

-j

dwa...@gmail.com

unread,
Nov 20, 2017, 12:49:18 PM11/20/17
to golang-nuts
It's also unsafe in the sense that it produces incorrect results: https://play.golang.org/p/mB71A4Q9bd 
 

Calum Shaw-Mackay

unread,
Nov 20, 2017, 8:18:43 PM11/20/17
to golang-nuts
I tend to be quite careful around removing items from an array/slice/list and not just in Go.

Deletion of items is probably the most mutable thing you can do to a list - if the list is shared between goroutines, it could really mess things up.
Rather than delete, I'd suggest a mark and copy approach instead, where you run through the slice once making a "To Delete" list, and copy those not scheduled for deletion into a new list. Its a tad inefficient, two loops through the user list, with a secondary allocation for your 'To Delete' list but I think it's fairly safe.

https://play.golang.org/p/Fu3QlEKb-t - has a full mark and copy sweep and a second version that does a single sweep with check and copy in the single loop

Calum

nil...@dinamize.net

unread,
Nov 20, 2017, 8:18:43 PM11/20/17
to golang-nuts
Don't use that way. You can try that another approach: https://play.golang.org/p/Nu8zD1stOd

DV

unread,
Nov 21, 2017, 1:51:16 PM11/21/17
to golang-nuts
I think that's a horrible idea in any language, honestly. You shouldn't be mutating the thing you're enumerating.

Jan Mercl

unread,
Nov 21, 2017, 1:57:31 PM11/21/17
to DV, golang-nuts
On Tue, Nov 21, 2017 at 7:51 PM DV <dimiter....@gmail.com> wrote:

> I think that's a horrible idea in any language, honestly. You shouldn't be mutating the thing you're enumerating.

Go specs, for example, take care to guarantee it's safe in at least some, if not all cases. Pruning eg. a map would otherwise incur a full copy penalty. So no, it's not a horrible idea in any language.

--

-j

Albert Tedja

unread,
Nov 21, 2017, 8:54:20 PM11/21/17
to golang-nuts
You need to swap elements if you want to remove them from list while iterating it. There are two ways to do this:

First: iterate backward. This will however, will change the order of unremoved elements.

Second: iterate forward, and will preserve the order of the unremoved elements.

https://play.golang.org/p/x2NMixEPI5

C Banning

unread,
Nov 22, 2017, 8:05:17 AM11/22/17
to golang-nuts
Why not something simple like: https://play.golang.org/p/iAlflMUdEA
Reply all
Reply to author
Forward
0 new messages