可分配性
如果满足以下条件之一,则 V 类型的值 x 可分配给 T 类型的变量(“x 可分配给 T”):
- V 和 T 具有相同的基础类型,但不是类型参数,并且 V 或 T 中至少有一个不是命名类型。
这是我的例子,证明这个规则不起作用: https://go.dev/play/p/fxXWkQM1O4_0
package main
import "fmt"
func main() {
example1()
example2()
}
func example1() {
type V int
var x V = 25
type T = int
var y T = x // unnamed type T
// ..or just `var y int = x` - same error
fmt.Println(y)
}
func example2() {
type V = int
var x V = 25 // unnamed type V
// ..or just `var x int = 25` - same error
type T int
var y T = x
fmt.Println(y)
}
出现以下错误:
./prog.go:15:12: cannot use x (variable of type V) as T value in variable declaration
./prog.go:29:12: cannot use x (variable of type V) as T value in variable declaration
规范中的这条规则有什么问题?
你能给我展示这个规则的一个有效示例吗?
在 Go 中,类型系统对于类型之间的可分配性有特定的规则,特别是在处理命名类型和类型别名时。让我们来分解一下您在
example1
和 example2
中遇到的问题。
example1
func example1() {
type V int
var x V = 25
type T = int
var y T = x // unnamed type T
fmt.Println(y)
}
事情是这样的:
V
是基于 int
的新命名类型。T
是 int
的类型别名,意味着 T
和 int
是相同的基础类型。当您尝试将
x
(类型为 V
)分配给 y
(类型为 T
)时,Go 的类型系统会认为 x
属于命名类型 (V
),并且 y
是别名类型 (T
)。尽管 T
和 int
是相同的基础类型,但由于命名类型 V
,T
和 V
被认为是不同的。
解决方案:您不能将
x
直接分配给 y
,因为 x
属于命名类型 (V
),并且 y
期望值为 T
(这是 int
的别名)
)。 Go 类型系统强制执行此规则以确保类型安全,因为它可以防止意外的类型不匹配。
example2
func example2() {
type V = int
var x V = 25 // unnamed type V
type T int
var y T = x
fmt.Println(y)
}
事情是这样的:
V
是 int
的别名,因此 V
和 int
是相同的底层类型。T
是基于 int
的新命名类型,因此 T
和 int
是不同的类型。当您尝试将
x
(V
类型)分配给 y
(T
类型)时,Go 的类型系统将 x
视为 int
的别名,并将 y
视为已命名的基于 int
的类型。尽管 x
是 int
的别名,但它不会自动匹配命名类型 T
,因为命名类型与其基础类型不同。
解决方案:与
example1
类似,您不能将x
(别名类型V
)分配给y
(命名类型T
)。由于命名类型规则,Go 类型系统将它们视为不同的。
在 Go 中:
type T int
创建)是不同的,即使它们具有相同的基础类型。type T = int
创建)被视为与其基础类型相同。因此,您不能在命名类型和类型别名的变量之间或两个不同的命名类型之间直接赋值,即使它们的基础类型相同。如果您想将一种类型分配给另一种类型,则需要在这些类型之间进行显式转换。
以下是如何修改示例以使其工作:
对于
example1
:
func example1() {
type V int
var x V = 25
type T = int
var y T = int(x) // Convert x to int
fmt.Println(y)
}
对于
example2
:
func example2() {
type V = int
var x V = 25
type T int
var y T = T(x) // Convert x to T
fmt.Println(y)
}
在这两种情况下,显式类型转换都用于弥合命名类型和别名类型之间的差距。