Go 是静态类型的编程语言。存储到变量中的值必须与变量的类型匹配。因此,不能像 Python 这种动态类型语言一样,随意的数据都可以作为值赋给变量。这个决定什么是允许赋值的规则就叫做可赋值性(Assignability)。
左边类型为 T 的变量,存在 6 种可以将右边的值赋给左边的情况。
1. 相同类型(Identical types)
第一种是非常明显的。如果右边的类型(也)是 T,则赋值是完全可以的。更多的细节可以参考 “Identical types in Go”。
2. 相同的基础类型(Identical underlying types)
在 Go 语言中,每种类型都有一种基础类型(underlying type)。对于布尔型,数字,字符串或者常量的基础类型都跟它们本身的类型相同。其他的基础类型来自于声明时的类型:
1 | type X map[string]int |
可赋值的第二种情况是相同的基础类型:
1 | type X map[string]int |
然而,如果有两个不同的命名类型(named types),则不能这么做:
1 | type X map[string]int |
附加的条件是要求至少一个类型不是一个命名类型。
Go 中的变量要么是命名类型(named)要么是非命名类型(unnamed)。非命名类型(unnamed types)是指使用类型字面意思(语言本身)定义的类型:
1 | var a [10]string |
3. 将一个实现了接口 T 的变量赋值给 T 接口类型的变量
如果一个变量实现了接口 T,那么我们可以将这个变量赋值给一个 T 接口类型的变量。
1 | type Callable interface { |
更多关于接口类型的细节都在 语言规范(language spec)。
4. 将双向管道(channel)的变量赋值给相同类型的变量(Assigning bidirectional channel to variable with identical element types)
1 | type T chan<- map[string]int |
跟第二种情况(相同的基础类型)一样,要求至少一种管道(channel)变量是非命名类型(unnamed type):
1 | type T chan<- map[string]int |
5. 赋值 nil(Assigning nil)
允许将 nil 赋值给指针,函数,切片,map,管道,接口类型(的变量)。
1 | var a *int |
6. 无(显式)指定类型的常量(Untyped constants)
关于 Go 常量更深入的介绍请查看官方博客
无(显式)指定类型的常量可以被赋值给常量所代表的类型 T 相同的类型为 T 的变量。
1 | var a float32 |
via: https://medium.com/golangspec/assignability-in-go-27805bcd5874
作者:Michał Łowicki
译者:Miancai Li
校对:polaris1119