W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
原文鏈接:https://gopl-zh.github.io/ch6/ch6-04.html
我們經(jīng)常選擇一個(gè)方法,并且在同一個(gè)表達(dá)式里執(zhí)行,比如常見(jiàn)的p.Distance()形式,實(shí)際上將其分成兩步來(lái)執(zhí)行也是可能的。p.Distance叫作“選擇器”,選擇器會(huì)返回一個(gè)方法“值”->一個(gè)將方法(Point.Distance)綁定到特定接收器變量的函數(shù)。這個(gè)函數(shù)可以不通過(guò)指定其接收器即可被調(diào)用;即調(diào)用時(shí)不需要指定接收器(譯注:因?yàn)橐呀?jīng)在前文中指定過(guò)了),只要傳入函數(shù)的參數(shù)即可:
p := Point{1, 2}
q := Point{4, 6}
distanceFromP := p.Distance // method value
fmt.Println(distanceFromP(q)) // "5"
var origin Point // {0, 0}
fmt.Println(distanceFromP(origin)) // "2.23606797749979", sqrt(5)
scaleP := p.ScaleBy // method value
scaleP(2) // p becomes (2, 4)
scaleP(3) // then (6, 12)
scaleP(10) // then (60, 120)
在一個(gè)包的API需要一個(gè)函數(shù)值、且調(diào)用方希望操作的是某一個(gè)綁定了對(duì)象的方法的話,方法“值”會(huì)非常實(shí)用(``=_=`真是繞)。舉例來(lái)說(shuō),下面例子中的time.AfterFunc這個(gè)函數(shù)的功能是在指定的延遲時(shí)間之后來(lái)執(zhí)行一個(gè)(譯注:另外的)函數(shù)。且這個(gè)函數(shù)操作的是一個(gè)Rocket對(duì)象r
type Rocket struct { /* ... */ }
func (r *Rocket) Launch() { /* ... */ }
r := new(Rocket)
time.AfterFunc(10 * time.Second, func() { r.Launch() })
直接用方法“值”傳入AfterFunc的話可以更為簡(jiǎn)短:
time.AfterFunc(10 * time.Second, r.Launch)
譯注:省掉了上面那個(gè)例子里的匿名函數(shù)。
和方法“值”相關(guān)的還有方法表達(dá)式。當(dāng)調(diào)用一個(gè)方法時(shí),與調(diào)用一個(gè)普通的函數(shù)相比,我們必須要用選擇器(p.Distance)語(yǔ)法來(lái)指定方法的接收器。
當(dāng)T是一個(gè)類(lèi)型時(shí),方法表達(dá)式可能會(huì)寫(xiě)作T.f
或者(*T).f
,會(huì)返回一個(gè)函數(shù)“值”,這種函數(shù)會(huì)將其第一個(gè)參數(shù)用作接收器,所以可以用通常(譯注:不寫(xiě)選擇器)的方式來(lái)對(duì)其進(jìn)行調(diào)用:
p := Point{1, 2}
q := Point{4, 6}
distance := Point.Distance // method expression
fmt.Println(distance(p, q)) // "5"
fmt.Printf("%T\n", distance) // "func(Point, Point) float64"
scale := (*Point).ScaleBy
scale(&p, 2)
fmt.Println(p) // "{2 4}"
fmt.Printf("%T\n", scale) // "func(*Point, float64)"
// 譯注:這個(gè)Distance實(shí)際上是指定了Point對(duì)象為接收器的一個(gè)方法func (p Point) Distance(),
// 但通過(guò)Point.Distance得到的函數(shù)需要比實(shí)際的Distance方法多一個(gè)參數(shù),
// 即其需要用第一個(gè)額外參數(shù)指定接收器,后面排列Distance方法的參數(shù)。
// 看起來(lái)本書(shū)中函數(shù)和方法的區(qū)別是指有沒(méi)有接收器,而不像其他語(yǔ)言那樣是指有沒(méi)有返回值。
當(dāng)你根據(jù)一個(gè)變量來(lái)決定調(diào)用同一個(gè)類(lèi)型的哪個(gè)函數(shù)時(shí),方法表達(dá)式就顯得很有用了。你可以根據(jù)選擇來(lái)調(diào)用接收器各不相同的方法。下面的例子,變量op代表Point類(lèi)型的addition或者subtraction方法,Path.TranslateBy方法會(huì)為其Path數(shù)組中的每一個(gè)Point來(lái)調(diào)用對(duì)應(yīng)的方法:
type Point struct{ X, Y float64 }
func (p Point) Add(q Point) Point { return Point{p.X + q.X, p.Y + q.Y} }
func (p Point) Sub(q Point) Point { return Point{p.X - q.X, p.Y - q.Y} }
type Path []Point
func (path Path) TranslateBy(offset Point, add bool) {
var op func(p, q Point) Point
if add {
op = Point.Add
} else {
op = Point.Sub
}
for i := range path {
// Call either path[i].Add(offset) or path[i].Sub(offset).
path[i] = op(path[i], offset)
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: