У Go struct складається з послідовності іменованих елементів, які називаються полями. Кожне поле має назву та тип.
Назва поля має бути унікальною в межах структури.
Структури можна порівняти з класами в парадигмі обʼєктно-орієнтованого програмування.
Ми створюємо нову структуру за допомогою ключових слів type і struct, а також явно визначаємо назву та тип її полів.
Наприклад, ось ми визначаємо структуру Shape, яка зберігає назву фігури та її розмір:
type Shape struct {
name string
size int
}
Назви полів у структурах дотримуються конвенції Go: поля, назва яких починається з малої літери, видимі лише коду в тому самому пакеті, а ті, назва яких починається з великої літери, видимі в інших пакетах.
Коли ми визначили struct, потрібно створити новий екземпляр, задавши поля за їхніми назвами в будь-якому порядку:
s := Shape {
name: "Square",
size: 25,
}
Щоб прочитати або змінити поля екземпляра, звертаємося до них через крапку .:
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
Поля, яким не присвоєно початкового значення, отримають нульове значення. Наприклад:
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
Можна створити екземпляр типу struct і без назв полів, якщо визначити поля в порядку:
s := Shape {
"Oval",
20,
}
Однак такий синтаксис вважається крихким кодом, бо він може зламатися, коли додають нове поле, особливо якщо це поле іншого типу.
У наступному прикладі ми додаємо до Shape ще одне поле:
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
Іноді буває зручно мати функції, які допомагають нам створювати екземпляри структур.
За конвенцією такі функції зазвичай називають New або дають їм назви, що починаються з New. Але оскільки це звичайні функції, ми можемо дати їм будь-яку назву.
Вони можуть нагадувати конструктори в інших мовах, але в Go вони залишаються просто звичайними функціями.
У наступному прикладі одну з таких функцій New використано, щоб створити новий екземпляр Shape й автоматично встановити типове значення для size фігури:
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
Використання функцій New має такі переваги:
New часто оголошують у тому самому пакеті, що й структури, які вони ініціалізують, вони можуть ініціалізувати навіть приватні поля цих структурУ цій вправі ми будемо організовувати гонки між різними типами радіокерованих машинок. Кожна машинка має власні характеристики швидкості та витрати заряду.
Машинки починають із повністю зарядженими батареями (100%). Щоразу, коли ми керуємо машинкою за допомогою пульта, вона проїжджає відстань, що дорівнює її швидкості в метрах, а відсоток заряду, що залишився, зменшується на величину витрати заряду.
Якщо заряд машинки менший за відсоток витрати заряду, керувати нею більше не можна.
Кожна траса має власну довжину. Машинки перевіряють на здатність проїхати трасу, не вичерпавши заряд.
Визначте структуру Car з такими полями типу int:
Забезпечте можливість створювати радіокеровану машинку, визначивши функцію NewCar, яка приймає швидкість машинки в метрах
і відсоток витрати заряду як свої два параметри (обидва типу int) та повертає екземпляр Car:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
// => Car{speed: 5, batteryDrain: 2, battery:100, distance: 0}
Визначте ще один тип структури під назвою Track з полем distance цілочисельного типу.
Забезпечте можливість створювати трасу, визначивши функцію NewTrack, яка приймає довжину траси в метрах як свій єдиний параметр (типу int):
distance := 800
track := NewTrack(distance)
// => Track{distance: 800}
Реалізуйте функцію Drive, яка оновлює кількість проїдених метрів відповідно до швидкості машинки та зменшує заряд відповідно до витрати заряду.
Якщо заряду не вистачає, щоб проїхати ще один раз, машинка не буде рухатися:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car = Drive(car)
// => Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}
Щоб завершити гонку, машинка повинна бути здатною проїхати всю дистанцію траси.
Це означає, що її заряд має не вичерпатися до того, як вона перетне фінішну лінію.
Реалізуйте функцію CanFinish, яка приймає екземпляри Car і Track як свої параметри та повертає true, якщо машинка може завершити гонку; інакше повертає false.
Вважайте, що ми зараз на стартовій лінії гонки та заводимо двигун машинки для гонки. Зважте на те, що на старті гонки батарея машинки може бути заряджена не повністю:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
distance := 100
track := NewTrack(distance)
CanFinish(car, track)
// => true
Зареєструйтеся на Exercism, щоб вивчати й опановувати Go, а також 34 концепції165 вправ та справжнє наставництво від людей, і все це безкоштовно.