I alias int to Int.
I want to convert a slice of Int to a slice of int, but got a compile error:
cannot convert c (type []Int) to type []int
How can I fix this? Thank you.
package main
import (
"fmt"
)
type Int int
func main() {
var c = []Int{}
var x = []int( c )
fmt.Println(len(x))
}
Your Int
type is not an alias of int
, it's a new type with int
being its underlying type. This type of conversion is not supported / allowed by the language spec. More specifically, converting a slice type to another where the element type is different is not allowed.
If you only need an []int
"view" of the []Int
, the safe way to "convert" would be to create a copy of the []Int
slice but with a type of []int
, and use a for range
loop and convert each individual element from Int
to int
type:
var c = []Int{1, 2}
x := make([]int, len(c))
for i, v := range c {
x[i] = int(v)
}
fmt.Println(x)
Output (try it on the Go Playground):
[1 2]
There is also an "unsafe" way:
var c = []Int{1, 2}
var x []int = *(*[]int)(unsafe.Pointer(&c))
fmt.Println(x)
Output is the same. Try this one on the Go Playground.
What happens here is that the address of c
(which is &c
) is converted to unsafe.Pointer
(all pointers can be converted to this), which then is converted to *[]int
(unsafe.Pointer
can be converted to any pointer type), and then this pointer is dereferenced which gives a value of type []int
. In this case it is safe because the memory layout of []Int
and []int
is identical (because Int
has int
as its underlying type), but in general, use of package unsafe
should be avoided whenever possible.
Int
would be a "true" aliasNote that if Int
would be a "true" alias to int
, the conversion would not even be needed:
var c = []Int{1, 2}
var x []int = c
fmt.Println(x)
Output is the same as above (try it on the Go Playground). The reason why this works is because writing []Int
is identical to writing []int
, they are the same type, so you don't even need a conversion here.
Also note that if you would create a new type with []int
as its underlying type, you could use type conversion:
type IntSlice = []int
func main() {
var c = IntSlice{1, 2}
var x []int = []int(c)
fmt.Println(x)
}
Output is again the same. Try this one on the Go Playground.
The problem is that you are not creating Int
as an alias, doing
type Int int
Will create Int
as a new type that can't interoperate with int
.
The proper way to create Int
as an alias is
type Int = int
With this change your program is ok.
Technically, type Int int
does not define an alias, but a completely new type. Even though Int
and int
now have identical underlying types and can be converted to each other, that does not apply to slices. More about allowed conversions is in the spec.
Actually, a slice a simply points to an underlying array of the designated type (in this case the types are different, Int
and int
). So unless your underlying type is the same a conversion won't work. Just to illustrate this something like this would work though:
package main
import (
"fmt"
)
type Int int
type IntSl []int
func main() {
var c = IntSl{2, 3, 4}
var x []int
x = []int(c)
var a Int
var b int
a = 1
b = int(a)
fmt.Println(len(x), a, b, c)
}
Playground : https://play.golang.org/p/ROOX1XoXg1j
As @icza points out there's the unsafe
way & of course you can always do the conversion looping over each of the elements which could be expensive.