轨道
/
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,全部免费。