尝试编写一个示例来证明 Golang 规范中的规则

问题描述 投票:0回答:1

可分配性

如果满足以下条件之一,则 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
1个回答
0
投票

在 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)
}

在这两种情况下,显式类型转换都用于弥合命名类型和别名类型之间的差距。

© www.soinside.com 2019 - 2024. All rights reserved.