Сборка мусора в Go
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 23 из 107.
В отличие от таких языков, как C или C++, Go автоматически управляет memory с помощью сборки мусора (GC). Вам не нужно вручную освобождать memory, когда вы заканчиваете с ней работу. Среда выполнения Go отслеживает, какая memory всё ещё используется, и возвращает остальную.
Когда вы выделяете память с помощью new(), make() или создавая переменные, сборщик мусора Go отслеживает эти выделения. Как только значение становится недоступным для любой части вашей программы, GC автоматически освобождает эту память.
func createPerson() *Person {
p := &Person{Name: "Alice", Age: 30}
return p // p уходит в кучу, GC будет управлять им
}
func main() {
person := createPerson()
fmt.Println(person.Name)
// Когда person больше не используется, GC освобождает память
}В этом примере структура Person выделяется в heap, потому что возвращается из function. Компилятор Go выполняет escape analysis, чтобы определить, может ли переменная оставаться в стеке или должна переместиться в heap. Сборщик мусора управляет только heap memory.
Это автоматическое управление memory означает, что ты можешь сосредоточиться на создании своего приложения, не беспокоясь об утечках memory из-за забытых освобождений. Однако понимание того, что существует GC, помогает писать более эффективный код, сводя к минимуму ненужные выделения, когда важна производительность.
Задание
ЛегкоДавайте создадим менеджер сессий, демонстрирующий, как сборщик мусора Go обрабатывает memory объектов, которые escape в heap. Вы создадите сессии, которые выделяются динамически и возвращаются из функций, позволяя GC управлять их жизненным циклом.
Вы организуете код в двух файлах:
session.go: Define структуруSessionс полямиID(string),Username(string) иData(срез строк). CreateNewSessionfunction, которая принимает ID и username, выделяет новый Session в heap (возвращая pointer) и инициализирует срез Data как empty. Также добавьте методAddDataс pointer receiver, который appends строку к срезу Data сессии, и методSummary, который возвращает formatted строку с details сессии.main.go: Прочитайте информацию о сессии из входных данных, создайте сессию с использованием вашей конструкторской function, добавьте в неё несколько entries данных и выведите сводку сессии. Поскольку сессия создаётся внутри function и возвращается как pointer, она escape в heap, где сборщик мусора будет ею управлять.
Будут предоставлены следующие входные данные:
- Строка 1: ID сессии
- Строка 2: Username
- Строка 3: Первая entry данных для добавления
- Строка 4: Вторая entry данных для добавления
Ваш метод Summary должен возвращать строку в следующем формате:
Session [ID] for user [Username]
Data entries: [count]
- [entry1]
- [entry2]Например, если заданы sess-001, alice, login и view_dashboard, результат должен быть следующим:
Session sess-001 for user alice
Data entries: 2
- login
- view_dashboardГлавная идея заключается в том, что ваша function NewSession creates Session и возвращает pointer на него. Это causes Session "escape" в heap вместо того, чтобы оставаться в стеке, благодаря чему он становится eligible для сборки мусора, когда ссылок на него больше не остаётся. Вашему коду не нужно вручную освобождать эту memory: Go обрабатывает её automatically.
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Читать ID сессии
sessionID, _ := reader.ReadString('\n')
sessionID = sessionID[:len(sessionID)-1]
// Читать имя пользователя
username, _ := reader.ReadString('\n')
username = username[:len(username)-1]
// Читать первую запись данных
data1, _ := reader.ReadString('\n')
data1 = data1[:len(data1)-1]
// Читать вторую запись данных
data2, _ := reader.ReadString('\n')
data2 = data2[:len(data2)-1]
// TODO: Создать новую сессию с помощью функции NewSession
// Сессия уйдёт в кучу, поскольку мы возвращаем указатель
// TODO: Добавить записи данных в сессию с помощью метода AddData
// TODO: Вывести сводку сессии с помощью метода Summary
fmt.Println("")
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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Потренируйтесь самостоятельно: Онлайн-компилятор Go