指针(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