使用指针接收器的方法

时间:2016-08-01 05:29:27

标签: go

我是计算机科学的新手。我只是从 The Go编程语言中读取下面的代码片段,并得到以下错误日志。

func (p *Point) ScaleBy(factor float64){
  p.X *= 2
  p.Y *= 2
}

Point{1, 2}.ScaleBy(2)
# error log
cannot call pointer method on point literal
cannot take the address of point literal
point literal.scaleby(2) used as value

本书解释说我们不能在不可寻址的Point接收器上调用*Point方法,因为无法获取临时值的地址。

但是,如果我打印&Point{1, 2},这不会引发错误。因此,为什么Point{1,2}是不可寻址的点接收器?

3 个答案:

答案 0 :(得分:1)

使用Point{1, 2}.ScaleBy(2),您尝试使用值ScaleBy调用指针接收方法Point{1, 2}

  

任何其他类型T的方法集由声明的所有方法组成   接收器类型为T。

但如果您使用可寻址类型:

  

相应指针类型* T的方法集是all的集合   用接收器* T或T声明的方法(也就是说,它还包含   方法集T)。

然后它是可能的:意味着您或编译器应该获取临时值的地址(获取复合文字的地址):

  

地址运营商:
  对于类型为T的操作数x,地址操作& x生成a   类型* T到x的指针。操作数必须是可寻址的,即   变量,指针间接或切片索引操作;   或可寻址结构操作数的字段选择器;或数组   可寻址数组的索引操作。作为例外   可寻址性要求,x也可以是(可能括在括号中)   复合文字。如果x的评估会导致运行时   恐慌,然后对& x的评价也是如此。

参考:https://golang.org/ref/spec#Address_operators

您可以致电(&Point{1, 2}).ScaleBy(2)
像这个工作示例代码(指针接收器):

package main

import "fmt"

func main() {
    p := (&Point{1, 2}).ScaleBy(2)
    fmt.Println(p) // &{2 4}
}

type Point struct {
    X, Y int
}

func (p *Point) ScaleBy(factor float64) *Point {
    p.X *= 2
    p.Y *= 2
    return p
}

你可以致电Point{1, 2}.ScaleBy(2)
喜欢这个工作示例代码(值接收器):

package main

import "fmt"

func main() {
    p := Point{1, 2}.ScaleBy(2)
    fmt.Println(p) // &{2 4}
}

type Point struct {
    X, Y int
}

func (p Point) ScaleBy(factor float64) *Point {
    p.X *= 2
    p.Y *= 2
    return &p
}

输出:

&{2 4}

还可以看到这个工作示例代码(指针接收器):

package main

import "fmt"

func main() {

    p := Point{1, 2}
    p.ScaleBy(2)

    fmt.Println(p) //  {2 4}
}

type Point struct {
    X, Y int
}

func (p *Point) ScaleBy(factor float64) {
    p.X *= 2
    p.Y *= 2
}

输出:

{2 4}

答案 1 :(得分:0)

获取复合文字的地址是该语言的一个特例。此语法生成指向使用文字值初始化的唯一变量的指针。复合文字本身不可寻址。

您可以使用此语法来调用方法:

(&Point{1, 2}).ScaleBy(2)

答案 2 :(得分:0)

当您撰写Point{1,2}时,您只需声明并初始化Point类型的即可。如果不将其分配给变量,则将其丢弃。

Go禁止在简单值上调用指针方法的这种行为,因为指针方法声明了对象的意图(由指针指向)修改。在大多数情况下,使用值调用的指针方法将无用,因为值会通过复制传递给方法。对该值进行的任何修改都将对该复制的值进行,并且不会发生实际修改。

如果你试过这个,它会起作用:

type Point struct {
    x, y int
}

func (p Point) X() {
    fmt.Println(p.x)
}

Point{1, 2}.X() // 1

您可以在此处详细了解:https://golang.org/doc/effective_go.html#pointers_vs_values