Метод - це функція з особливим аргументом, одержувачем.
Одержувач стоїть у власному списку аргументів між ключовим словом 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!
Звернімо увагу, як ми викликали метод Greetings() у p, екземплярі Person.
Це точно так само, як ми викликаємо методи в обʼєктно-орієнтованій мові програмування.
Памʼятаймо: метод - це просто функція з аргументом-одержувачем. Методи допомагають уникати конфліктів імен: метод привʼязаний до конкретного типу одержувача, тому одну й ту саму назву методу можна мати для різних типів.
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>%".Кожна траса має власну довжину. Машини перевіряють на те, чи можуть вони проїхати трасу, не розрядивши батарею.
Реалізуйте метод Drive на Car, який оновлює кількість пройдених метрів відповідно до швидкості машини та зменшує заряд батареї відповідно до її витрати:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car.Drive()
// car is now Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}
Примітка: не намагайтеся керувати машиною, якщо від цього заряд її батареї стане меншим за 0.
Реалізуйте метод DisplayDistance на Car, який повертає відстань такою, як вона відображається на LED-дисплеї, у вигляді string:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
fmt.Println(car.DisplayDistance())
// Output: "Driven 0 meters"
Реалізуйте метод DisplayBattery на Car, який повертає відсоток заряду батареї таким, як він відображається на LED-дисплеї, у вигляді string:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
fmt.Println(car.DisplayBattery())
// Output: "Battery at 100%"
Щоб фінішувати в перегонах, машина повинна мати змогу проїхати всю дистанцію перегонів.
Це означає, що вона не повинна розрядити батарею, не перетнувши фінішну лінію.
Реалізуйте метод CanFinish, який приймає параметр trackDistance int і повертає true, якщо машина може фінішувати в перегонах, або false в іншому разі:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
trackDistance := 100
car.CanFinish(trackDistance)
// => true
Зареєструйтеся на Exercism, щоб вивчати й опановувати Go, а також 34 концепції166 вправ та справжнє наставництво від людей, і все це безкоштовно.