Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove element of struct array in loop in golang

Tags:

Problem

I have array of structs:

type Config struct {   Applications []Application } 

Note: Config - is a struct for json.Decode.

config = new(Config) _ = decoder.Decode(&config) 

In loop I have some condition and element deletion by key.

for i, application := range config.Applications {   if i == 1 {     config.Applications = _removeApplication(i, config.Applications)   } }  func _removeApplication(i int, list []Application) []Application {   if i < len(list)-1 {     list = append(list[:i], list[i+1:]...)   } else {     log.Print(list[i].Name)     list = list[:i]   }    return list } 

But always I have "out of range" error. What is the best way to delete element by key from array of structs?

like image 623
Alex Pliutau Avatar asked Mar 12 '15 09:03

Alex Pliutau


People also ask

How do you get rid of a slice in Golang?

To remove the first element, call remove(s, 0), to remove the second, call remove(s, 1), and so on and so forth. Hm, not really. This: s[i] = s[len(s)-1] definitely copies the last element to the element at index i . Then, return s[:len(s)-1] returns the slice without the last element.

How do I delete a structure in Golang?

The garbage collector will properly remove objects from memory when they become unreachable. You can assign nil to maps and slices because nil is a valid value (the zero value) for those types. The zero value for struct types is not nil but a struct value where all its fields have their zero values.

How do you remove slices from an element?

Removing an Element from a Slice Items need to be removed from a slice by slicing them out. To remove an element, you must slice out the items before that element, slice out the items after that element, then append these two new slices together without the element that you wanted to remove.


2 Answers

Quoting from the Slice Tricks page deleting the element at index i:

a = append(a[:i], a[i+1:]...) // or a = a[:i+copy(a[i:], a[i+1:])] 

Note that if you plan to delete elements from the slice you're currently looping over, that may cause problems. And it does if the element you remove is the current one (or a previous element already looped over) because after the deletion all subsequent elements are shifted, but the range loop does not know about this and will still increment the index and you skip one element.

You can avoid this by using a downward loop:

for i := len(config.Applications) - 1; i >= 0; i-- {     application := config.Applications[i]     // Condition to decide if current element has to be deleted:     if haveToDelete {         config.Applications = append(config.Applications[:i],                 config.Applications[i+1:]...)     } } 
like image 116
icza Avatar answered Sep 18 '22 15:09

icza


You are getting this error because you are doing a loop over a slice with an inital range of X length that became X-n because you remove some elements during loop.

If you want to delete an item at a specific index from a slice, you can do it this way:

sliceA = append(sliceA[:indexOfElementToRemove], sliceA[indexOfElementToRemove+1:]...) 
like image 26
gdg Avatar answered Sep 21 '22 15:09

gdg