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?
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.
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.
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.
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:]...) } }
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:]...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With