Storing slice structures by value is bad. They are copied there every time.
And this is not a niggle, so your memory will flow.
Imagine that you added 1000 elements in [] Hello, the slice refers to the array where these 1000 elements are stored (and the capacity may actually be more necessary and then new(Hello) will be there), but then you decided to delete 500, and you didn’t move the slice window in the underlying array to always store either your “deleted” structures, or you’ll have to overwrite them with new(Hello) elements (then the garbage collector will remove the deleted ones) and it will still eat memory like for cap (list) elements . So far, of course, you will not add 500 elements again and then they will really go over and the garbage collector will be able to pick them up. And if you have a “fat” structure with a large number of fields and / or nested structures (by reference or copy), channels, and other things, then all this will also remain in memory until you overwrite with new elements.
The correct approach will store a slice of pointers, they at least eat memory, regardless of the number of fields and their type in the structure.
type Hello struct {} ... var list []*Hello ... hello1 := &Hello{} hello2 := &Hello{} hello3 := &Hello{} list = append(list, hello1, hello2, hello3)
Then the function to remove
func Remove(list []*Hello, item *Hello) []*Hello { for i, v := range list { if v == item { copy(list[i:], list[i+1:]) list[len(list)-1] = nil // обнуляем "хвост" list = list[:len(list)-1] } } return list }
Moreover, the comparison v == item will work correctly even if it is two different pointers to the same structure.
And you can delete as
list = Remove(list, hello2)
Notice that the slice needs to be reassigned as with the addition.
About zeroing tail. If you simply reduce the length of the slice, then in the underlying array there will still be a link to the structure that you no longer need, and the garbage collector will not be able to pick it up.
Useful techniques Slice tricks