Frequently Asked Questions:variant types? slice类型转换?

519 阅读2分钟

这是我参与更文挑战的第8天,活动详情查看: 更文挑战

能把[]T转换为[]interface{}吗?

答案是:不能直接转换。这是因为根据语言的规范,这两种类型在内存中的表现并不相同。如果要转的话,就一定需要把slice中的元素单独地一个地个得转化。下面是一个把int数组转化为interface数组的例子。

t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
    s[i] = v
}
specification 规范

如果T1和T2的类型相同,能够把[]T1转化为[]T2吗?

下面例子中最后一行,是无法通过编译的。

type T1 int
type T2 int
var t1 T1
var x = T2(t1) // OK
var st1 []T1
var sx = ([]T2)(st1) // NOT OK

在Go语言中,类型和一些方法紧密的绑定在一起,也就是所有类型都有一些绑定的方法。一个通用规则是这样:你可以改变一个类型(可能会一起改变它绑定的方法集),但是你不能改变一个复合类型(含有一系列的元素)(PS:因此map也是不能直接转化的)。

Go要求你明确的进行类型转换(PS:就是集合的话,你要一个一个来转化)

Go为什么没有variant types?

variant types , 比较熟知的名字是代数类型。它的能让值表现为多种类型,但是只能是指定的一些类型。编程中一个常见的例子就是一个error,可能是网络错误、安全错误或者是一个应用错误,它允许程序员通过区分错误类型来确定错误的来源。另一个例子是一个语法树,其中每个节点可以是不同类型的:声明,语句,分配等等。

我们考虑过添加variant types (变量类型),但在讨论后决定不采用,因为它们与接口的使用会让人感到困惑。 试想一下:如果variant types 中的元素就是它们本身的接口,那该怎么处理呢?

此外,其实variant types 一些显著的特点其实Go语言已经做到了。 例如上述的error示例,我们可以使用接口,用它的value来保存error,type来区分错误的类型。 语法树示例也是可行的,虽然可能不太优雅。

discriminate 歧视,区分
overlap v 重叠