2016-08-01 34 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}