Итоги — Обобщенная коллекция
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy — урок 72 из 107.
Задание
ЛегкоДавайте создадим универсальную структуру данных Queue (очередь), которая продемонстрирует все, что вы узнали о дженериках в Go! В отличие от стека (LIFO), очередь следует принципу First-In-First-Out (FIFO) — первый добавленный элемент удаляется первым.
Вы организуете свой код в двух файлах:
queue.go: Определите вашу универсальную коллекцию очереди.Создайте универсальную структуру
Queue[T any], которая хранит элементы внутри. Ваша очередь должна поддерживать следующие операции:Enqueue(item T)— добавляет элемент в конец очередиDequeue() (T, bool)— удаляет и возвращает элемент из начала очереди вместе с логическим значением, указывающим на успех (возвращает нулевое значение иfalse, если очередь пуста)Peek() (T, bool)— возвращает первый элемент без его удаления (тот же шаблон возврата, что и у Dequeue)Size() int— возвращает количество элементов в очередиIsEmpty() bool— возвращает true, если в очереди нет элементов
Также создайте функцию-конструктор
NewQueue[T any]() *Queue[T], которая возвращает указатель на инициализированную пустую очередь.main.go: Продемонстрируйте работу вашей очереди с различными типами на основе входных данных.Прочитайте индикатор типа (
intилиstring), затем прочитайте серию команд для выполнения над очередью. Каждая команда находится на отдельной строке:enqueue [value]— добавить значение в очередьdequeue— удалить и вывести первый элемент (вывестиempty, если очередь пуста)peek— вывести первый элемент без удаления (вывестиempty, если очередь пуста)size— вывести текущий размер
Читайте команды, пока не получите
done.
Будут предоставлены следующие входные данные:
- Строка 1: Индикатор типа (
intилиstring) - Следующие строки: Команды до
done
Например, при вводе:
int
enqueue 10
enqueue 20
enqueue 30
peek
dequeue
size
dequeue
dequeue
dequeue
doneВаш вывод должен быть:
10
10
2
20
30
emptyИ при вводе:
string
enqueue hello
enqueue world
size
peek
dequeue
peek
doneВаш вывод должен быть:
2
hello
hello
worldВаша очередь должна работать одинаково как для целых чисел, так и для строковых типов, демонстрируя, как одна универсальная реализация обрабатывает несколько конкретных типов, сохраняя при этом полную безопасность типов.
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Считать индикатор типа
scanner.Scan()
typeIndicator := scanner.Text()
if typeIndicator == "int" {
// TODO: Create an integer queue using NewQueue[int]()
// Обработать команды для целочисленной очереди
for scanner.Scan() {
line := scanner.Text()
if line == "done" {
break
}
parts := strings.SplitN(line, " ", 2)
command := parts[0]
// TODO: Handle commands: enqueue, dequeue, peek, size
// Для enqueue извлечь целочисленное значение из parts[1]
// Для dequeue/peek вывести "empty", если очередь пуста
_ = command
}
} else if typeIndicator == "string" {
// TODO: Create a string queue using NewQueue[string]()
// Обработать команды для строковой очереди
for scanner.Scan() {
line := scanner.Text()
if line == "done" {
break
}
parts := strings.SplitN(line, " ", 2)
command := parts[0]
// TODO: Handle commands: enqueue, dequeue, peek, size
// Для enqueue использовать строковое значение из parts[1]
// Для dequeue/peek вывести "empty", если очередь пуста
_ = command
}
}
// Они здесь, чтобы избежать ошибок неиспользуемого импорта во время разработки
_ = strconv.Atoi
_ = 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