Структуры в Go: организация данных и поведение
В этом уроке мы изучим структуры — один из самых мощных инструментов Go для организации данных и поведения. Структуры позволяют создавать сложные типы данных, которые могут содержать как данные, так и методы для работы с ними.
Почему важны структуры?
Структуры в Go необходимы для:
- Группировки связанных данных
- Создания пользовательских типов
- Инкапсуляции данных и поведения
- Реализации объектно-ориентированного подхода
- Создания сложных структур данных
💡 Интересный факт: В Go нет классов, но структуры с методами позволяют реализовать многие концепции объектно-ориентированного программирования.
Основы структур
1. Создание и использование структур
type Person struct {
Name string
Age int
Address struct {
City string
Country string
}
}
func main() {
// Создание структуры
person := Person{
Name: "Иван",
Age: 30,
Address: struct {
City string
Country string
}{
City: "Москва",
Country: "Россия",
},
}
// Доступ к полям
fmt.Printf("%s живёт в %s\n", person.Name, person.Address.City)
}
2. Методы структур
type Rectangle struct {
Width float64
Height float64
}
// Метод с получателем-значением
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// Метод с получателем-указателем
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
func main() {
rect := Rectangle{Width: 10, Height: 5}
fmt.Println("Площадь:", rect.Area())
rect.Scale(2)
fmt.Println("Новая площадь:", rect.Area())
}
Продвинутые техники
1. Встраивание структур
type Animal struct {
Name string
Age int
}
type Dog struct {
Animal
Breed string
}
func (a Animal) Speak() string {
return "Я животное"
}
func (d Dog) Speak() string {
return "Гав-гав!"
}
func main() {
dog := Dog{
Animal: Animal{Name: "Рекс", Age: 3},
Breed: "Овчарка",
}
fmt.Println(dog.Name) // Доступ к встроенному полю
fmt.Println(dog.Speak()) // Вызов переопределённого метода
}
2. Интерфейсы и структуры
type Speaker interface {
Speak() string
}
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return "Мяу!"
}
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
cat := Cat{Name: "Мурзик"}
MakeSound(cat)
}
3. Теги структур
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Password string `json:"-"` // Поле будет пропущено при сериализации
CreatedAt time.Time `json:"created_at"`
}
func main() {
user := User{
ID: 1,
Username: "admin",
Password: "secret",
CreatedAt: time.Now(),
}
data, _ := json.Marshal(user)
fmt.Println(string(data))
}
Практические примеры
1. Кэш с TTL
type Cache struct {
mu sync.RWMutex
items map[string]struct {
value interface{}
expiration time.Time
}
}
func (c *Cache) Set(key string, value interface{}, ttl time.Duration) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = struct {
value interface{}
expiration time.Time
}{
value: value,
expiration: time.Now().Add(ttl),
}
}
func (c *Cache) Get(key string) (interface{}, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
item, exists := c.items[key]
if !exists || time.Now().After(item.expiration) {
return nil, false
}
return item.value, true
}
2. Очередь задач
type Task struct {
ID string
Payload interface{}
Priority int
CreatedAt time.Time
}
type TaskQueue struct {
tasks chan Task
wg sync.WaitGroup
}
func NewTaskQueue(workers int) *TaskQueue {
q := &TaskQueue{
tasks: make(chan Task, 100),
}
q.wg.Add(workers)
for i := 0; i < workers; i++ {
go q.worker()
}
return q
}
func (q *TaskQueue) worker() {
defer q.wg.Done()
for task := range q.tasks {
// Обработка задачи
fmt.Printf("Обработка задачи %s\n", task.ID)
}
}
Практические задания
Задание 1: Система управления библиотекой
Создайте структуры для:
- Книги (название, автор, год издания, статус)
- Читателя (имя, контакты, список взятых книг)
- Библиотеки (каталог книг, список читателей) Реализуйте методы для:
- Выдачи и возврата книг
- Поиска книг по различным критериям
- Отслеживания статуса книг
Задание 2: Система управления задачами
Разработайте систему для:
- Создания и управления задачами
- Назначения задач пользователям
- Отслеживания прогресса
- Установки приоритетов и сроков Используйте:
- Вложенные структуры
- Методы с указателями
- Интерфейсы для разных типов задач
Задание 3: Система мониторинга
Создайте систему для:
- Сбора метрик с серверов
- Хранения исторических данных
- Генерации отчётов
- Оповещения о проблемах Реализуйте:
- Потокобезопасные структуры данных
- Эффективное хранение временных рядов
- Гибкую систему оповещений
Что дальше?
В следующем уроке мы:
- Изучим интерфейсы в Go
- Познакомимся с рефлексией
- Узнаем о тегах структур
- Начнём писать более сложные программы
🎯 Цель урока: К концу этого урока вы должны уметь:
- Создавать и использовать структуры
- Работать с методами и указателями
- Применять встраивание структур
- Использовать теги для сериализации