A. 关于结构体的类型转换#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| package main
type S0 struct {
y int "foo"
x bool
}
type S1 = struct { // S1是一个无名类型
x int "foo"
y bool
}
type S2 = struct { // S2也是一个无名类型
x int "bar"
y bool
}
type S3 S2 // S3是一个定义类型(因而具名)。
type S4 S3 // S4是一个定义类型(因而具名)。
// 如果不考虑字段标签,S3(S4)和S1的底层类型一样。
// 如果考虑字段标签,S3(S4)和S1的底层类型不一样。
var v0, v1, v2, v3, v4 = S0{}, S1{}, S2{}, S3{}, S4{}
func f() {
v1 = S1(v2); v2 = S2(v1)
v1 = S1(v3); v3 = S3(v1)
v1 = S1(v4); v4 = S4(v1)
v2 = v3; v3 = v2 // 这两个转换可以是隐式的
v2 = v4; v4 = v2 // 这两个转换也可以是隐式的
v3 = S3(v4); v4 = S4(v3)
}
|
回顾定义:
- 具名类型:有标识符表示的类型(预声明类型、定义类型)。
- 无名类型:没有标识符的类型,通常是组合类型。
s1, s2 是组合类型–>无名类型
s3, s4 是定义类型 (type x y)–>具名类型
S0
不能与其他类型相互转换,因为字段名不同。S1
和 S2
需要显式转换,因为它们的字段标签不同。S2
可以隐式转换为 S3
和 S4
,因为 S3
和 S4
的底层类型是 S2
。S3
和 S4
之间需要显式转换,因为它们都是具名类型。
B. 为什么都是具名类型要显示转换#
B.1. 类型安全性#
具名类型在 Go 中被视为不同的类型,即使它们的底层类型相同。这种设计是为了确保类型安全,防止在不兼容的类型之间进行错误的操作。通过要求显式转换,程序员必须明确地表明他们知道正在进行的类型转换,并且确认这种转换是合理的。
B.2. 明确性#
显式转换使代码更具可读性和明确性。它清楚地表明了程序员的意图,表明他们有意识地在不同的具名类型之间进行转换。这有助于其他开发者理解代码的逻辑和意图,减少误解和错误。
因此,显式转换在具名类型之间是必要的,以确保代码的安全性和可读性。
C. 结构体值类型转换规则#
Responsive Image