我将我的Int
类型定义为int
。
我想将一个Int
切片转换为int
切片,但是出现了编译错误:
无法将c(类型[]Int)转换为类型[]int
我该如何修复这个问题?
package main
import (
"fmt"
)
type Int int
func main() {
var c = []Int{}
var x = []int( c )
fmt.Println(len(x))
}
我将我的Int
类型定义为int
。
我想将一个Int
切片转换为int
切片,但是出现了编译错误:
无法将c(类型[]Int)转换为类型[]int
我该如何修复这个问题?
package main
import (
"fmt"
)
type Int int
func main() {
var c = []Int{}
var x = []int( c )
fmt.Println(len(x))
}
你的 Int
类型并不是 int
的别名,它是一种具有 int
作为底层类型的新类型。这种类型的转换在语言规范中不受支持/允许。更具体地说,不允许将元素类型不同的切片类型转换为另一个切片类型。
如果你只需要一个 []int
对 []Int
的"视图",安全的"转换"方式是创建一个具有 []int
类型但数据与 []Int
相同的副本,并使用 for range
循环将每个单独的元素从 Int
转换为 int
类型:
var c = []Int{1, 2}
x := make([]int, len(c))
for i, v := range c {
x[i] = int(v)
}
fmt.Println(x)
输出结果(在Go Playground上试一下):
[1 2]
还有一种“不安全”的方式:
var c = []Int{1, 2}
var x []int = *(*[]int)(unsafe.Pointer(&c))
fmt.Println(x)
输出相同。在Go Playground上尝试这个。
这里发生的是,c
的地址(即&c
)被转换为unsafe.Pointer
(所有指针都可以转换为它),然后将其转换为*[]int
(unsafe.Pointer
可以转换为任何指针类型),然后解引用此指针,得到类型为[]int
的值。在这种情况下,它是安全的,因为[]Int
和[]int
的内存布局是相同的(因为Int
具有int
作为其基础类型),但一般来说,应尽可能避免使用unsafe
包。
Int
是一个“真正的”别名请注意,如果Int
是int
的“真正的”别名,甚至不需要进行转换:
var c = []Int{1, 2}
var x []int = c
fmt.Println(x)
输出结果与上面相同(在Go Playground上尝试)。这个方法有效的原因是,使用[]Int
和[]int
等同,它们是相同的类型,因此您甚至不需要进行转换。
还要注意,如果您使用[]int
作为其基础类型创建一个新类型,则可以使用类型转换:
type IntSlice = []int
func main() {
var c = IntSlice{1, 2}
var x []int = []int(c)
fmt.Println(x)
}
输出结果再次相同。在Go Playground上尝试一下。
unsafe
的应用程序将在未来版本和所有平台上继续工作。这种不安全的解决方案在未来的版本中破坏的可能性很小,但不能保证。有保证的是,在将来的版本中,安全的方式也将在所有平台上继续工作。 - icza其实,一个切片只是简单地指向了一个指定类型的底层数组(在这种情况下,类型是不同的,Int
和 int
)。所以,除非你的底层类型是相同的,否则转换是行不通的。但是,为了说明这一点,像这样做就可以:
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)
}
实验室: https://play.golang.org/p/ROOX1XoXg1j
正如 @icza 指出的那样,有一种不安全的方法,当然你也可以遍历每个元素进行转换,但这可能是很昂贵的。
Int
创建为别名,而是这样做:
type Int int
int
互操作的新类型。Int
别名的正确方法是:
type Int = int