學習軌道
/
Go
Go
/
練習
/
Jedlik 的玩具
Jedlik 的玩具

Jedlik 的玩具

學習練習

簡介

方法是一種帶有特殊_接收者_引數的函式。 接收者會出現在自己的引數清單中,介於func關鍵字和方法名稱之間。

func (receiver type) MethodName(parameters) (returnTypes) {
}

只有當接收者的型別和方法定義在同一個套件裡時,你才能定義這個方法。

package person 

type Person struct {
	Name string
}

func (p Person) Greetings() string {
	return fmt.Sprintf("Welcome %s!", p.Name)
}

定義在結構體上的方法可以用點記法呼叫。

p := Person{Name: "Bronson"}
fmt.Println(p.Greetings())
// Output: Welcome Bronson!

注意我們在Person實例p上呼叫Greetings()方法的方式。 這和你在物件導向程式語言中呼叫方法的方式完全一樣。

記住:方法就只是帶有接收者引數的函式。 方法有助於避免命名衝突,因為方法會綁定到特定的接收者型別,所以你可以在不同的型別上使用相同的方法名稱。

import "math"

type rect struct {
	width, height int
}
func (r rect) area() int {
	return r.width * r.height
}

type circle struct {
	radius int
}
func (c circle) area() float64 {
	return math.Pow(float64(c.radius), 2) * math.Pi
}

接收者分為兩種:值接收者和指標接收者。

到目前為止我們看過的方法都使用值接收者,這表示它們收到的會是傳入方法的值的副本,也就是說,在方法內對接收者所做的任何修改,都不會被呼叫端看見。

你可以宣告使用指標接收者的方法,藉此修改接收者所指向的值。 做法是在型別名稱前面加上*。 例如以rect型別來說,指標接收者會宣告成*rect。 這類修改同樣會被方法的呼叫端看見。

type rect struct {
	width, height int
}
func (r *rect) squareIt() {
	r.height = r.width
}

r := rect{width: 10, height: 20}
fmt.Printf("Width: %d, Height: %d\n", r.width, r.height)
// Output: Width: 10, Height: 20

r.squareIt()
fmt.Printf("Width: %d, Height: %d\n", r.width, r.height)
// Output: Width: 10, Height: 10

說明

注意:這項練習是need-for-speed練習的延續。

在這項練習中,你將要組織各種遙控車之間的比賽。 每輛車都有自己的速度和電池耗電特性。

車輛一開始的電池是滿的(100%)。 每次你使用遙控器駕駛車輛時,車輛會前進相當於其速度的公尺數,並依其電池耗電量減少剩餘的電池百分比。

如果車輛的電池低於其電池耗電百分比,就無法再駕駛該車輛。

這台遙控車有一個花俏的 LED 顯示器,會顯示兩項資訊:

  • 已行駛的總距離,顯示為:"Driven <METERS> meters"。
  • 剩餘的電池電量,顯示為:"Battery at <PERCENTAGE>%"。

每條賽道都有自己的距離。 車輛的測試方式是檢查它們是否能在不耗盡電池的情況下完成賽道。

1. 駕駛車輛

在Car上實作Drive方法,根據車輛的速度更新已行駛的公尺數,並依照電池耗電量減少電池電量:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car.Drive()
// car is now Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}

注意:如果駕駛車輛會導致電池電量低於 0,就不應該嘗試駕駛。

2. 顯示已行駛的距離

在Car上實作DisplayDistance方法,以string形式回傳 LED 顯示器上顯示的距離:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)

fmt.Println(car.DisplayDistance())
// Output: "Driven 0 meters"

3. 顯示電池百分比

在Car上實作DisplayBattery方法,以string形式回傳 LED 顯示器上顯示的電池百分比:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)

fmt.Println(car.DisplayBattery())
// Output: "Battery at 100%"

4. 檢查遙控車是否能完成比賽

為了完成比賽,車輛必須能夠行駛賽道的距離。 這表示在越過終點線之前不能耗盡電池。 實作CanFinish方法,該方法接受trackDistance int作為參數,如果車輛能完成比賽則回傳true;否則回傳false:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)

trackDistance := 100

car.CanFinish(trackDistance)
// => true
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Go Exercism

準備好開始 Jedlik 的玩具 了嗎?

註冊 Exercism,透過 34 個概念166 個練習 和真人引導來學習並精通 Go,全部免費。