我是计算机科学的新手。我只是从 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}
是不可寻址的点接收器?
答案 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