blob: 04ae3f3166723948def98824f74ecd6daa7a87b3 [file] [log] [blame] [view]
Andrew Gerrand5bc444d2014-12-10 11:35:11 +11001# Introduction
2
3Given that you can assign a variable of any type to an ` interface{} `, often people will try code like the following.
4```
Dave Day0d6986a2014-12-10 15:02:18 +11005var dataSlice []int = foo()
6var interfaceSlice []interface{} = dataSlice
Andrew Gerrand5bc444d2014-12-10 11:35:11 +11007```
8This gets the error
9```
10cannot use dataSlice (type []int) as type []interface { } in assignment
11```
12
13The question then, "Why can't I assign any slice to an ` []interface{} `, when I can assign any type to an ` interface{} `?"
14
15## Why?
16
17There are two main reasons for this.
18
19The first is that a variable with type ` []interface{} ` is not an interface! It is a slice whose element type happens to be ` interface{} `. But even given this, one might say that the meaning is clear.
20
21Well, is it? A variable with type ` []interface{} ` has a specific memory layout, known at compile time.
22
23Each ` interface{} ` takes up two words (one word for the type of what is contained, the other word for either the contained data or a pointer to it). As a consequence, a slice with length N and with type ` []interface{} ` is backed by a chunk of data that is N\*2 words long.
24
25This is different than the chunk of data backing a slice with type ` []MyType ` and the same length. Its chunk of data will be N\*sizeof(MyType) words long.
26
27The result is that you cannot quickly assign something of type ` []MyType ` to something of type ` []interface{} `; the data behind them just look different.
28
29## What can I do instead?
30
31It depends on what you wanted to do in the first place.
32
33If you want a container for an arbitrary array type, and you plan on changing back to the original type before doing any indexing operations, you can just use an ` interface{} `. The code will be generic (if not compile-time type-safe) and fast.
34
35If you really want a ` []interface{} ` because you'll be doing indexing before converting back, or you are using a particular interface type and you want to use its methods, you will have to make a copy of the slice.
36```
Dave Day0d6986a2014-12-10 15:02:18 +110037var dataSlice []int = foo()
38var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
39for i, d := range dataSlice {
40 interfaceSlice[i] = d
41}
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110042```