2016-08-01 169 views
1

我是计算机科学的新手。我刚刚从下面的代码片段中看到了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{1, 2},这不会抛出错误。因此,为什么Point{1,2}是不可寻址的Point Receiver?

回答

0

考虑复合文字的地址是该语言中的一种特殊情况。该语法生成​​一个指向由文字值初始化的唯一变量的指针。复合文字本身不可寻址。

你可以使用这个语法来调用方法:

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

当你写Point{1,2}你只是声明和初始化Point类型的。如果您不将它分配给一个变量,它将被丢弃。

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

如果你想这一点,它的工作:

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

1

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

任何其他类型T的方法集由所有声明为 的方法组成,其中接收方t YPE T.

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

对应的指针类型* T的方法集合是与接收机* T或T(即声明的所有 方法,它还包含了T)的方法集合 。

则是可能的:这意味着你或者编译器应该得到暂时值的地址(以复合文字的地址):

地址符:
对于类型的操作数X T,地址操作& x生成一个 类型* 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}