0

I want to remove an item in a slice w/o having to use a specific function for every type of items in the slice. So, I am using interface{} as the slice item type:

package main

import "fmt"

func sliceRemoveItem(slice []interface{}, s int) []interface{} {
  return append(slice[:s], slice[s+1:]...)
}

func main() {
  array := []int{1,2,3,4,5,6,7}

  fmt.Println(array)
  fmt.Println(sliceRemoveItem(array,1))
}

But goLang doesn't like it:

./prog.go:13:30: cannot use array (type []int) as type []interface {} in argument to sliceRemoveItem

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

Any idea how to do this? Is it possible to use a generic single function accepting any type of slice items?

Refs: How to delete an element from a Slice in Golang

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
  • 1
    Until generics arrive, this could only be solved with reflection. So recommended way is to "inline" the element removal code manually, or use a type-specific helper function. – icza Aug 27 '20 at 10:35
  • 2
    https://golang.org/doc/faq#convert_slice_of_interface – Volker Aug 27 '20 at 10:58
  • 1
    "Is it possible to use a generic single function accepting any type of slice items?" Yes. You need reflection but it is **not** worth the trouble. Get used to write a functions two or three times. – Volker Aug 27 '20 at 10:59
  • 1
    @Juan if my answer helped you, please consider accepting it. – Z. Kosanovic Sep 13 '20 at 00:29

2 Answers2

4

You're trying to pass a slice of int as a slice of interface{}. Go doesn't do this conversion implicitly since it is a costly operation.

Check out this answer: https://stackoverflow.com/a/12754757

You can either accept []interface{}, but do the conversion explicitly, or specify the type as []int. This works:

package main

import "fmt"

func sliceRemoveItem(slice []int, s int) []int {
  return append(slice[:s], slice[s+1:]...)
}

func main() {
  array := []int{1,2,3,4,5,6,7}

  fmt.Println(array)
  fmt.Println(sliceRemoveItem(array,1))
}
Z. Kosanovic
  • 727
  • 4
  • 10
2

Use the reflect package.

// sliceRemoveItem removes item at index i from the
// slice pointed to by slicep.
func sliceRemoveItem(slicep interface{}, i int) {
    v := reflect.ValueOf(slicep).Elem()
    v.Set(reflect.AppendSlice(v.Slice(0, i), v.Slice(i+1, v.Len())))
}

Call it like this:

slice := []int{1, 2, 3, 4, 5, 6, 7}
sliceRemoveItem(&slice, 1)

To avoid type assertions in the caller, the function uses a pointer to slice argument.

Run it on the Go playground