By danny


2012-10-05 20:48:07 8 Comments

I'm curious why Go does't implicitly convert []T to []interface{} when it will implicitly convert T to interface{}. Is there something non-trivial about this conversion that I'm missing?

Example:

func foo([]interface{}) { /* do something */ }

func main() {
    var a []string = []string{"hello", "world"}
    foo(a)
}

go build complains

cannot use a (type []string) as type []interface {} in function argument

And if I try to do it explicitly, same thing: b := []interface{}(a) complains

cannot convert a (type []string) to type []interface {}

So every time I need to do this conversion (which seems to come up a lot), I've been doing something like this:

b = make([]interface{}, len(a), len(a))
for i := range a {
    b[i] = a[i]
}

Is there a better way to do this, or standard library functions to help with these conversions? It seems kind of silly to write 4 extra lines of code every time I want to call a function that can take a list of e.g. ints or strings.

5 comments

@yala ramesh 2019-03-25 13:06:29

Convert interface{} into any type.

Syntax:

result := interface.(datatype)

Example:

var employee interface{} = []string{"Jhon", "Arya"}
result := employee.([]string)   //result type is []string.

@Nick Craig-Wood 2012-10-06 08:12:52

The thing you are missing is that T and interface{} which holds a value of T have different representations in memory so can't be trivially converted.

A variable of type T is just its value in memory. There is no associated type information (in Go every variable has a single type known at compile time not at run time). It is represented in memory like this:

  • value

An interface{} holding a variable of type T is represented in memory like this

  • pointer to type T
  • value

So coming back to your original question: why go does't implicitly convert []T to []interface{}?

Converting []T to []interface{} would involve creating a new slice of interface {} values which is a non-trivial operation since the in-memory layout is completely different.

@weberc2 2014-09-18 16:23:05

This is informative and well written (+1), but you're not addressing the other part of his question: "Is there a better way to do this..." (-1).

@Stephen Weinberg 2012-10-05 22:16:52

In Go, there is a general rule that syntax should not hide complex/costly operations. Converting a string to an interface{} is done in O(1) time. Converting a []string to an interface{} is also done in O(1) time since a slice is still one value. However, converting a []string to an []interface{} is O(n) time because each element of the slice must be converted to an interface{}.

The one exception to this rule is converting strings. When converting a string to and from a []byte or a []rune, Go does O(n) work even though conversions are "syntax".

There is no standard library function that will do this conversion for you. You could make one with reflect, but it would be slower than the three line option.

Example with reflection:

func InterfaceSlice(slice interface{}) []interface{} {
    s := reflect.ValueOf(slice)
    if s.Kind() != reflect.Slice {
        panic("InterfaceSlice() given a non-slice type")
    }

    ret := make([]interface{}, s.Len())

    for i:=0; i<s.Len(); i++ {
        ret[i] = s.Index(i).Interface()
    }

    return ret
}

Your best option though is just to use the lines of code you gave in your question:

b := make([]interface{}, len(a))
for i := range a {
    b[i] = a[i]
}

@newacct 2012-10-05 23:32:40

it might be slower, but it would work generically with any type of slice

@RickyA 2016-05-25 12:28:04

This whole answer applies to maps too btw.

@Justin Ohms 2017-09-05 17:59:31

This also applies to channels as well.

@Mayur 2019-06-04 08:57:18

Thanks for clear explanation, if possible can you add ref. for Converting a []string to an interface{} is also done in O(1) time?

@Yandry Pozo 2016-10-20 23:03:59

Here is the official explanation: https://github.com/golang/go/wiki/InterfaceSlice

var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
    interfaceSlice[i] = d
}

@dskinner 2012-10-05 21:56:23

Try interface{} instead. To cast back as slice, try

func foo(bar interface{}) {
    s := bar.([]string)
    // ...
}

@kostix 2012-10-10 07:53:31

This begs for the next question: how the OP is then supposed to iterate over bar so as to interpret it as "a slice of any type"? Note that his three-liner creates a []interface{}, not []string or a slice of other concrete type.

@weberc2 2014-09-18 16:20:56

-1: This only works if bar is []string, in which case, you may as well write: func foo(bar []string) { /* ... */ }

@dskinner 2014-09-18 22:02:58

use a type switch, or use reflection as in the accepted answer.

@Cassiohg 2019-05-10 09:31:10

OP is going to have to figure out his type at run time any way. Using non slice interface{} will make the compiler not complain when passing an argument as in foo(a). He could either use reflect or type switching (golang.org/doc/effective_go.html#type_switch) inside foo.

Related Questions

Sponsored Content

6 Answered Questions

[SOLVED] Checking the equality of two slices

  • 2013-03-09 14:46:38
  • wei2912
  • 83960 View
  • 229 Score
  • 6 Answer
  • Tags:   go go-reflect

0 Answered Questions

Type casting function loaded from a library to function with empty interface parameter

  • 2019-07-23 08:22:08
  • Sobat Binangkit
  • 38 View
  • 0 Score
  • 0 Answer
  • Tags:   go

12 Answered Questions

[SOLVED] How to convert a zero-terminated byte array to string?

  • 2013-01-09 07:19:48
  • Derrick Zhang
  • 453620 View
  • 467 Score
  • 12 Answer
  • Tags:   go

12 Answered Questions

[SOLVED] How to find a type of an object in Go?

  • 2013-11-24 02:08:13
  • Rahul
  • 289706 View
  • 321 Score
  • 12 Answer
  • Tags:   go go-reflect

7 Answered Questions

[SOLVED] Convert between slices of different types

  • 2012-08-12 17:20:18
  • slartibartfast
  • 31038 View
  • 40 Score
  • 7 Answer
  • Tags:   go go-reflect

3 Answered Questions

[SOLVED] interface{} to function type conversion

  • 2014-07-07 13:11:16
  • stan.sm
  • 5603 View
  • 11 Score
  • 3 Answer
  • Tags:   go

1 Answered Questions

2 Answered Questions

[SOLVED] Using a string slice where a slice of empty interface is expected

  • 2014-09-23 20:24:50
  • djdick
  • 722 View
  • 1 Score
  • 2 Answer
  • Tags:   go slice

3 Answered Questions

2 Answered Questions

[SOLVED] Does Go allow specification of an interface for a map with particular key type?

  • 2012-11-08 15:21:28
  • Bill Katz
  • 297 View
  • 2 Score
  • 2 Answer
  • Tags:   interface go

Sponsored Content