《GO語言聖經》讀書筆記(五) 方法

2021-10-07 14:01:43 字數 4460 閱讀 2514

本節讀書筆記對應原書第六章。

​ 在函式宣告時,在其名字之前放上乙個變數,就是乙個方法。

package geometry

import

"math"

type point struct

func

(p point)

distance

(q point)

float64

func

distance

(q,p point)

float64

​ 這裡提供了兩個distance,第乙個distance就是乙個方法,附加的引數p是方法的接收器,表示distance屬於point這種型別的獨有方法,第二個distance就是乙個傳統的函式。早期的說法:呼叫乙個方法稱為向乙個物件傳送訊息。

​ 我們可以任意選擇接收器的名字,但建議接收器的名字要統一和簡短,此外,一般是不適用this或者self作為接收器的。

​ 下面看一下這兩種方式如何被使用的。

p:=point

q:=point

fmt.

println

(distance

(p,q)

)//使用包級別的函式distance

fmt.

println

(p.distance

(q))

//使用point類下生命的point.distance方法

​ 這裡多說一句,如果在包外呼叫的時候,使用方法會比函式更簡短,因為呼叫包級別的函式需要寫包名,舉個例子。

import

"gopl.io/ch6/geometry"

perim := geometry.path,,

,}fmt.

println

(geometry.path.

distance

(perim)

)// "12", standalone function

fmt.

println

(perim.

distance()

)// "12", method of geometry.path

總結:

​ 當呼叫乙個函式的時候,會對其每乙個引數值進行拷貝,如果乙個函式需要更新乙個變數,或者函式的其中乙個引數實在太大,那麼應使用指標來宣告方法。

type point2 struct

func

(p *point2)

scaleby

(factor float64

)

​ 該方法的名字就是(*point).scaleby。如果point2這個類有乙個指標作為接收器的方法,那麼所有point2的方法都必須有乙個指標接收器,即使是那些並不需要這個指標接收器的函式。如果乙個型別本身就是乙個指標的話,那是不能出現在接收器中的,就像下面這樣會出現compile error

type p *

intfunc

(p)f()

​ 呼叫指標型別方法有3種方法,以呼叫指標型別方法(*point2).scaleby為例:

//first

r :=

&point2

r.scaleby(2

)fmt.

println

(*r)

// ""

//second

p := point2

pptr :=

&ppptr.

scaleby(2

)fmt.

println

(p)// ""

//third

p := point2

(&p)

.scaleby(2

)fmt.

println

(p)// ""

​ 其實還有簡短的寫法:

p:= point2

p.scaleby(2

)

​ 編譯器會隱式用&p呼叫scaleby方法,不過這種簡寫只適合變數。不能通過乙個無法取到位址的接收器(比如臨時變數的記憶體位址)來呼叫指標方法。

point

.scaleby(2

)// compile error

注意:

import

"image/color"

type point struct

type coloredpoint struct

func

(p point)

distance

(q point)

float64

​ point這個型別嵌入到coloredpoint來提供x和y這兩個字段 ,可以把coloredpoint型別當作接收器來呼叫point裡的方法,point類的方法也被引入了coloredpoint 。

​ distance有乙個引數是point型別, 但q雖然有point這個內嵌型別,但它並不是point型別,使用時要顯式地選擇。

p.

distance

(q)// compile error: cannot use q (coloredpoint) as point

p.distance

(q.point)

//right

​ 結構體中也可以內嵌乙個型別的指標,這種情況下字段和方法會被間接引入到當前型別中,訪問的時候通過這個指標指向的物件去取。

type coloredpoint struct

p:= coloredpoint

, red}

q := coloredpoint

, blue}

fmt.

println

(p.distance

(*q.point)

)// "5"

q.point = p.point // p and q now share the same point

p.scaleby(2

)fmt.

println

(*p.point,

*q.point)

// " "

p := point

q := point

distancefromp := p.distance // method value

fmt.

println

(distancefromp

(q))

fmt.

println

(p.distance

(q))

​ 為了說明這兩個概念,還是先看個例子。我們呼叫乙個方法一般採用p.distance(q)形式一步到位,但實際上等價於兩步,首先將選擇器返回的方法值儲存到乙個變數中distancefromp := p.distance,這其實是將方法繫結到特定接收器變數的函式,然後呼叫時直接傳入引數就可以了distancefromp(q)。和之前的方式比,似乎少了乙個接收器p,其實我們之前已經指定過了。

​ 下面說方法表示式,方法表示式就是剛剛的p.distance,方法表示式返回的是方法值。如果t是乙個型別,方法表示式可能寫作t.f或者(*t).f,如何使用方法表示式最合適呢?

​ 使用方法表示式,可以根據選擇來呼叫接收器各不相同的方法。如下所示,我們可以為path陣列中的每乙個point來呼叫對應的sub或者add方法。

type point struct

func

(p point)

add(q point) point

}func

(p point)

sub(q point) point

}type path [

]point

func

(path path)

translateby

(offset point, add bool

)else

for i :=

range path

}

初學c 讀書筆記(五) 方法A

1 方法結構 方法是一塊具有名稱的 可以使用方法名執行 也可以把資料傳入方法並接收資料輸出。方法的特徵 方法是否返回資料,如果返回,返回什麼型別 方法名什麼型別的輸入可以傳入方法 方法體包含可以執行 的語句序列。intsum intvar1,intvar2 2 本地變數 本地變數用於儲存本地的或臨時...

初學c 讀書筆記(五) 方法C

12 棧幀 當乙個方法被呼叫時,在棧頂分配了一塊記憶體用於儲存一定數量與方法相關的資料項,這塊記憶體叫方法的棧幀 棧幀儲存以下資訊 返回位址 分配記憶體的引數 與方法呼叫相關的其他各種管理資料項 方法被呼叫時,它的整個棧幀被壓入棧中 方法退出時,它的整個棧幀被從棧中彈出 class program ...

初學c 讀書筆記(五) 方法B

6 引數 形參因為形參是變數,所以有型別和名稱,並能寫入和讀取 形參在方法體的外面定義並在方法開始之前初始化 引數列表中可以有人一數目的形參,使用逗號隔開 實參用於初始化形參的表示式或變數稱為實參 實參放在方法呼叫的引數列表中 實參的數目與形引數目相同,且型別相匹配 7 值引數 使用值引數,資料通過...