问题描述
我想知道为什么这段代码在 go 中编译。我预计会出现编译器错误,例如字符串:
package main
import (
"fmt"
)
type myMap map[string]int
type mySlice []int
type myChan chan int
type myString string
func main() {
var mm myMap
var m map[string]int
m = mm // fine,but expected compiler error
var ms mySlice
var s []int
s = ms // same with slices
var mc myChan
var c chan int
c = mc // or channels
var mstr myString
var str string
// str = mstr // error,as expected
fmt.Printf("%T %T %T %T %T %T %T %T\n",mm,m,ms,s,mc,c,mstr,str)
}
Playground
为什么我在使用那些特殊的“引用类型”映射、切片和 chan 时不会出现类型不匹配错误?
解决方法
在前两种情况下您不会遇到编译时错误,因为语言规范允许这些赋值。
在赋值中,每个值都必须是 assignable 到它被赋值的操作数的类型...
值 x
可分配给 T
类型的 variable(“x
可分配给 T
”)如果以下条件之一适用:
-
x
的类型与T
相同。 x
的类型V
和T
具有相同的 underlying types 并且至少V
或T
之一不是defined 类型。-
T
是接口类型,x
implementsT
。 -
x
是双向通道值,T
是通道类型,x
的类型V
和T
具有相同的元素类型,并且在V
或T
中的至少一个不是定义的类型。 -
x
是预先声明的标识符nil
,T
是指针、函数、切片、映射、通道或接口类型。 -
x
是类型为T
的值的无类型 constant representable。
强调规则适用于您的前 2 个案例。但是,它不适用于您的最后一种情况,因为 string
和 myString
都是已定义的类型。没有任何规则适用于您的最后一种情况。
根据语言规范:
x 的类型 V 和 T 具有相同的底层类型,并且 V 或 T 中至少有一个不是定义的类型。
myMap
是一个定义的类型,但 map[string]int
不是,而且由于底层类型是相同的,所以赋值是有效的。
string
是一个定义的类型,所以分配给另一个定义的类型不起作用。您必须明确复制。