Go 指针与价值方法

示例

指针方法

即使变量本身不是指针,也可以调用指针方法。

根据Go Spec,

。。。如果使用指针指针接收器使用可寻址的值对非接口方法的引用,则会自动采用该值的地址:t.Mp等效于(&t).Mp。

您可以在此示例中看到以下内容:

package main

import "fmt"

type Foo struct {
    Bar int
}

func (f *Foo) Increment() {
   f.Bar+= 1
}

func main() {
    var f Foo

    // Calling `f.Increment` is automatically changed to `(&f).Increment` by the compiler.
    f = Foo{}
    fmt.Printf("f.Bar is %d\n", f.Bar)
    f.Increment()
    fmt.Printf("f.Bar is %d\n", f.Bar)
    
    // As you can see, calling `(&f).Increment` directly does the same thing.
    f = Foo{}
    fmt.Printf("f.Bar is %d\n", f.Bar)
    (&f).Increment()
    fmt.Printf("f.Bar is %d\n", f.Bar)
}

价值方法

与指针方法类似,即使变量本身不是值,也可以调用值方法。

根据Go Spec,

。。。使用指针对具有值接收器的非接口方法的引用将自动取消引用该指针:pt.Mv等效于(*pt).Mv。

您可以在此示例中看到以下内容:

package main

import "fmt"

type Foo struct {
    Bar int
}

func (f Foo) Increment() {
   f.Bar+= 1
}

func main() {
    var p *Foo

    // 编译器会自动将调用p.Increment更改为`(* p).Increment`。
    // (请注意,由于编辑* p的副本而不是原始的* p,`* p`将保持为0)
    p = &Foo{}
    fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
    p.Increment()
    fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
    
    // 如您所见,直接调用`(* p).Increment`可以完成相同的操作。
    p = &Foo{}
    fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
    (*p).Increment()
    fmt.Printf("(*p).Bar is %d\n", (*p).Bar)
}


要了解有关指针和值方法的更多信息,请访问“方法值”的“执行规范”部分,或参阅“指针与值”的“有效执行”部分。


注1:像这样的选择器()周围*p和&f之前的括号().Bar用于分组,必须保留。

注2:尽管当指针是方法的接收者时可以将其转换为值(反之亦然),但是当指针作为函数内部的参数时,它们不会自动相互转换。