指针(pointer)
PythonGo
&
i := 42
p := &i
pi
*typepointer*type*pointerpointer
i := 42
p := &i
*p = 420
// i = 420
pi*pii420p*p
func operPointer(p *int) {
*p = *p * 100
// 接受的参数是个指针
// 函数内通过*pointer设置指针所指向的值
// *Type代表接受一个指针;
// 而*Pointer却代表操作指针所指向的值
}
调用该函数
func PointerKey1() {
i := 10
// p := &i
// p是i的指针
// operPointer(p)
operPointer(&i)
fmt.Println(i)
}
i1000&iiipp
只有接受指针的函数才能操作原始数据,反之则通常是操作了一个传入的数据的副本。比如下面这样子——
func operValue(p int) int {
p = p * 100
return p
}
func PointerKey2() {
i := 10
operValue(i)
fmt.Println(i)
}
i10operValue()i
结构体(struct)
结构体是一种类型,结构体类型通常包含一个或多个字段。
type MyNumbers struct {
X, Y int
}
mMyNumbers
func M() {
m := MyNumbers{}
fmt.Println(m)
}
运行结果如下。因为没有为其赋值,所以会赋予对应类型的零值。
{0 0}
fmt.Printf("%T\n", m)包名.类型名
advanced.MyNumbers
.
func M() {
m := MyNumbers{10, 20}
// fmt.Println(m)
// fmt.Printf("%T\n", m)
fmt.Println(m.X)
fmt.Println(m.Y)
}
运行结果为
10
20
结构体 & 指针
*pointer(*pointer).fieldGopointer.field
func Scale5P(p *MyNumbers) {
p.X = p.X * 5
p.Y = p.Y * 5
//可以通过指针直接访问值
//Go编译器翻译为了(*i).X和(*i).Y
}
Scale5P()MyNumbersp
func PointerKey3() {
i := MyNumbers{1, 2}
// Scale5P(i)
Scale5P(&i)
// 而对于函数Scale5P()来说, 由于接受的参数是个指针, 所以必须传入&i
fmt.Println(i)
}
i
{5 10}
方法(method)和结构体
PythonselfGoGo
func (receiver recevier-type) method-name() return-type {
codes...
}
(接收者 接收者类型)
func (i MyNumbers) Scale100() MyNumbers {
i.X = i.X * 100
i.Y = i.Y * 100
return i
}
Scale100()MyNumbersMyNumbers.
func PointerKey2() {
i := MyNumbers{1, 2}
i.Scale100() //如前所述, 这里的调用传入的是i的副本
fmt.Println(i)
}
i{1 2}Scale100类型类型的指针GoGoself指针
而下面这个函数就可以对调用它的变量的原始数据直接作修改了。
func (p *MyNumbers) Scale100P() {
p.X = p.X * 100
p.Y = p.Y * 100
}
GoScale100P()值
func PointerKey5() {
i := MyNumbers{1, 2}
// p := &i
i.Scale100P() //所以为了实现类似面向对象语言里self的效果, 就必须要定义接收者为指针的方法
// Scale100P的接收者为一个指针(或者说它是指针的方法), 但却可以直接通过i调用
// Go编译器其实自动翻译为了(&i).Scale100P()
fmt.Println(i)
}
小结
PythonGo
值 = 函数(值)GoGoself