如何在go中将切片转换为别名切片? [关闭]

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.

The safe way

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]

The unsafe way

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.

If Int would be a "true" alias

Note 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.

By using a slice type

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.