Вложенные структуры
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy — урок 16 из 107.
Вложенная структура — это структура, которая содержит другую именованную структуру в качестве одного из своих полей. Это позволяет моделировать сложные иерархические данные путем объединения более мелких и переиспользуемых типов вместе.
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // вложенная структура
}Для доступа к полям во вложенной структуре вы соединяете имена полей через точку.
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // BostonВложенность способствует повторному использованию кода. Тип Address может использоваться в нескольких структурах, таких как Person, Company или Order, без дублирования полей. Этот подход отражает отношения в реальном мире, где сущности содержат другие сущности.
type Company struct {
Name string
Employees int
Address Address // используется тот же тип Address
}Вы можете вкладывать структуры на несколько уровней вглубь, хотя сохранение иерархий неглубокими улучшает читаемость. Вложенные структуры являются основополагающими для построения объектно-ориентированных моделей данных в Go.
Задание
ЛегкоДавайте создадим систему управления сотрудниками, которая демонстрирует, как вложенные структуры помогают моделировать иерархии реального мира. Вы создадите структуру, в которой сотрудники относятся к отделам, а отделы содержат информацию о местоположении.
Вы организуете свой код в двух файлах:
models.go: Определите три структуры, которые работают вместе:Locationс полямиBuilding(string) иFloor(int)Departmentс полемName(string) и вложенным полемLocationEmployeeс полямиID(int),Name(string) и вложенным полемDepartment
main.go: Считайте информацию о сотруднике из входных данных, создайте объект Employee с правильно вложенными структурами и выведите полный профиль сотрудника, обращаясь к полям через вложенную структуру.
Будут предоставлены следующие входные данные:
- Строка 1: ID сотрудника (целое число)
- Строка 2: Имя сотрудника
- Строка 3: Название отдела
- Строка 4: Название здания
- Строка 5: Номер этажа (целое число)
Формат вывода:
Employee: [Name] (ID: [ID])
Department: [DepartmentName]
Location: [Building], Floor [Floor]Например, для входных данных 101, Alice Chen, Engineering, Tower A и 5, ваш вывод должен быть:
Employee: Alice Chen (ID: 101)
Department: Engineering
Location: Tower A, Floor 5Обращайтесь к вложенным полям, используя точечную нотацию для перехода по иерархии структур (например, employee.Department.Location.Building).
Шпаргалка
Вложенная структура — это структура, которая содержит другую именованную структуру в качестве одного из своих полей, что позволяет моделировать иерархические данные путем объединения более мелких, переиспользуемых типов.
Определение вложенных структур
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // вложенная структура
}Доступ к вложенным полям
Используйте точечную нотацию для перемещения по иерархии структур:
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // BostonПовторное использование вложенных структур
Один и тот же тип вложенной структуры можно повторно использовать в нескольких родительских структурах:
type Company struct {
Name string
Employees int
Address Address // тот же тип Address используется повторно
}Вложенные структуры способствуют повторному использованию кода и отражают реальные отношения, в которых одни сущности содержат другие. Вы можете вкладывать структуры на несколько уровней вглубь, хотя сохранение неглубокой иерархии улучшает читаемость.
Попробуйте сами
package main
import "fmt"
func main() {
// Чтение информации о сотруднике
var id int
var name string
var deptName string
var building string
var floor int
fmt.Scanln(&id)
fmt.Scanln(&name)
fmt.Scanln(&deptName)
fmt.Scanln(&building)
fmt.Scanln(&floor)
// TODO: Создайте Employee с правильно вложенными структурами
// Используйте структуры Location, Department и Employee из models.go
// Инициализируйте все вложенные поля входными значениями
// TODO: Выведите профиль сотрудника, используя формат:
// Employee: [Name] (ID: [ID])
// Department: [DepartmentName]
// Location: [Building], Floor [Floor]
// Обращайтесь к вложенным полям, используя точечную нотацию (например, employee.Department.Location.Building)
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП в Go
Внешние файлыРабочее пространство и модули GoПакеты и импортыЭкспортируемые и неэкспортируемые именаВведение в ООП в GoСтруктуры как классыОпределение методов структурПолучатели-указатели и получатели-значенияИнициализация структурФункции-конструкторыИтоги — Простой калькулятор4Интерфейсы
Введение в интерфейсыНеявная реализацияИнтерфейс как контрактПустой интерфейс (any)Утверждение типаПереключатель типовКомпозиция интерфейсовИнтерфейсы Stringer и ErrorПовторение: Калькулятор фигур7Инкапсуляция
Экспортируемые и неэкспортируемые поляИнкапсуляция на уровне пакетовГеттеры и сеттерыСокрытие информации в GoИтоги — Записи о студентах10Обобщения (Generics) (Go 1.18+)
Введение в GenericsПараметры типовОграничения типовОбобщенные структурыОбходной путь для обобщенных методовИтоги — Обобщенная коллекция13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн Abstract FactoryПаттерн ObserverПаттерн Strategy2Глубокое погружение в типы и структуры
Базовые и составные типыОпределение пользовательских типовТеги структурАнонимные структурыВложенные структурыНулевые значения и значения по умолчаниюПовторение — Контактная книга5Композиция вместо наследования
Почему в Go нет наследованияОсновы встраивания структурПродвижение методовВстраивание нескольких структурВстраивание против агрегацииЗатенение встроенных методовИтоги — Иерархия сотрудников8Обработка ошибок и ООП
Интерфейс errorПользовательские типы ошибокОбертывание ошибок (fmt.Errorf)Sentinel-ошибкиerrors.Is() и errors.As()Panic, Defer и RecoverИтоги — Парсер файлов11Стандартная библиотека и ООП
io.Reader и io.Writersort.InterfaceИнтерфейс fmt.Stringerencoding/json со структурамиИнтерфейс http.HandlerПовторение: модели REST API14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикMiddleware как Декоратор3Указатели и память
Основы указателей в GoУказатели на структурыПередача по значению и по ссылкеФункция new()Сборка мусора в GoПовторение: Конструктор связного списка6Полиморфизм в Go
Полиморфизм через интерфейсыУтиная типизация в GoПравила реализации интерфейсовПолиморфные коллекцииВнедрение зависимостейИтоги — Обработчик платежей9Конкурентность и ООП
Основы горутинКаналы и взаимодействиеБуферизованные и небуферизованные каналыОператор selectsync.Mutex и sync.RWMutexsync.WaitGroupПроектирование потокобезопасных структурПовторение — Worker Pool