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