forked from basicExploration/Demos
/
go编译器内部真实处理的三种方式.go
86 lines (66 loc) · 2.37 KB
/
go编译器内部真实处理的三种方式.go
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 演示 go编译器内部真实处理的三种方式
//
//
//总结一下 go的method ,不管是定义在指针上或者是值上的方法,用值和指针都可以取到,
//第二:定义在指针上的方法,你根本不用取* 值就可以获取到结果,因为编译器帮你做了,
//这个仅仅是在对象取值这一步仅此而已。如果你的value是指针类型,然后你还是想对它进行处理的时候你需要取值才能操作,
//因为一个指针 一个钥匙啥的完全没办法操作值,所以go的编译器经常帮你做了很多事情,第一个说明里 & *的智能添加,
//第二个说名中 对指针对象自动取值的添加。这是两部分,
package main
import "fmt"
func main() {
// 第一种帮你自动取&
ts := a{
"12",
}
ts.tt()
//内部是:
ts = a{
"12",
}
(&ts).tt()
// 第二种帮你自动取*
tss := new(a)
tss.ttpl()
//内部是:
tss = new(a)
(*tss).ttpl()
// 上面是第一种情况的说明,
//第二种情况
tsss := new(a)
tsss.tt()
// 看内部说明
//func (a1 *a) tt() {
// a1.value += "1"
// fmt.Println(a1.value)
//}
//这里面 a1 是 a的指针类型,然后输入的也是指针,这个没的说,但是能取到value值,就不能了,原因是编译器做了:
//(*a1).value
//ps:下面说明一种情况 上面的第一种情况下,系统帮你自动取了& 是因为要满足"定义在指针上的方法" 这个要求,然后内部就又
// 取了* 获取了值才能获取对象。这是编译器的内部过程。
}
type a struct {
value string
}
func (a1 *a) tt() { //常用模式
a1.value += "1"
fmt.Println(a1.value)
}
//func (a1 *a) tt() { //这个才是内部实现的真实面貌。
// (*a1).value += "1"
// fmt.Println((*a1).value)
// fmt.Println("这才是真实的面貌")
//}
func (a2 a) ttpl() {
a2.value += "1"
fmt.Println(a2.value)
}
// ps: 如果是在接口中,这个规则就改了,谁实现的方法谁才能实现这个接口(这里面的谁谁 说的是 指针类型和 值类型)
// 说到go的编译器,其实 例如闭包 循环体中的变量,都是用的引用类型,在用的时候go编译器直接给你自动取* 了。这就是编译器的小技巧了。
// ## 输出结果:
//证明了理论。以后定将剖析 go的源代码来看看编译器这个小家伙到底是怎么做到的。
// 121
// 121
// 1
// 1
// 1