Система выдачи книг
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 100 из 107.
Задание
ЛегкоДавайте создадим систему выдачи книг для нашего проекта Library Management! Вы создадите структуру Library, которая управляет коллекциями книг и пользователей, с методами для обработки операций выдачи и возврата, включая надлежащую проверку данных.
Вы организуете код в четырех файлах:
book.go: ваша структураBookиз предыдущего урока с полямиID,Title,Author,ISBNиAvailable. Включите конструкторNewBook, который инициализирует книги как доступные.user.go: ваша структураUserс полямиID,Name,EmailиBorrowedBooks(срезом ID книг). Включите конструкторNewUser, который инициализирует пользователей с пустым списком выданных книг.library.go: создайте структуруLibrary, которая хранит книги и пользователей в отображениях (с ключами, соответствующими их ID). Реализуйте следующие компоненты:- конструктор
NewLibrary, который инициализирует пустые отображения для книг и пользователей - метод
AddBook, который добавляет книгу в библиотеку - метод
AddUser, который добавляет пользователя в библиотеку - метод
Borrow, который принимает ID пользователя и ID книги, проверяет операцию, помечает книгу как недоступную, добавляет ID книги в список выданных книг пользователя и возвращает ошибку, если что-то пошло не так - метод
Return, который отменяет процесс выдачи: помечает книгу как доступную и удаляет ее из списка выданных книг пользователя
Метод
Borrowдолжен возвращать следующие ошибки:user not found, если ID пользователя не существуетbook not found, если ID книги не существуетbook not available, если книга уже выдана
Метод
Returnдолжен возвращать следующие ошибки:user not found, если ID пользователя не существуетbook not found, если ID книги не существуетbook not borrowed, если книга уже доступна
- конструктор
main.go: объедините все компоненты, создав библиотеку, добавив книги и пользователей, а затем обработав операции выдачи и возврата.Прочитайте количество книг, затем для каждой книги прочитайте ее ID, название, автора и ISBN. Затем прочитайте количество пользователей и для каждого пользователя — его ID, имя и email. После этого прочитайте количество операций, где каждая операция имеет вид
borrow [userID] [bookID]илиreturn [userID] [bookID].Для каждой операции выведите
OKв случае успеха илиError: [message]в случае ошибки.
Будут предоставлены следующие входные данные:
- Количество книг, затем ID, название, автора и ISBN каждой книги (каждое значение в отдельной строке)
- Количество пользователей, затем ID, имя и email каждого пользователя (каждое значение в отдельной строке)
- Количество операций, затем каждая операция в отдельной строке
Например, для следующих данных:
2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.com
4
borrow U001 B001
borrow U001 B001
return U001 B001
borrow U002 B001Вывод должен быть таким:
OK
Error: book not available
OK
Error: user not foundА для следующих данных:
1
B100
Design Patterns
Gang of Four
978-0201633610
2
U001
Bob Jones
bob@email.com
U002
Carol White
carol@email.com
3
borrow U001 B100
borrow U002 B100
return U001 B100Вывод должен быть таким:
OK
Error: book not available
OKА для следующих данных:
1
B001
Go in Action
William Kennedy
978-1617291784
1
U001
Dave Miller
dave@test.com
2
return U001 B001
borrow U001 B999Вывод должен быть таким:
Error: book not borrowed
Error: book not foundОбратите внимание, как Library выступает в роли центрального координатора. Она проверяет все операции перед изменением состояния, обеспечивая синхронизацию книг и пользователей. Использование указателей-получателей позволяет вашим методам изменять фактические данные, хранящиеся в отображениях!
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Прочитать количество книг
var numBooks int
fmt.Fscanln(reader, &numBooks)
// TODO: Создать новую библиотеку
// TODO: Прочитать данные каждой книги (ID, Title, Author, ISBN на отдельных строках)
// и добавить их в библиотеку
for i := 0; i < numBooks; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
author, _ := reader.ReadString('\n')
author = strings.TrimSpace(author)
isbn, _ := reader.ReadString('\n')
isbn = strings.TrimSpace(isbn)
// TODO: Создать книгу и добавить в библиотеку
}
// Прочитать количество пользователей
var numUsers int
fmt.Fscanln(reader, &numUsers)
// TODO: Прочитать данные каждого пользователя (ID, Name, Email на отдельных строках)
// и добавить их в библиотеку
for i := 0; i < numUsers; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
email, _ := reader.ReadString('\n')
email = strings.TrimSpace(email)
// TODO: Создать пользователя и добавить в библиотеку
}
// Прочитать количество операций
var numOps int
fmt.Fscanln(reader, &numOps)
// TODO: Обработать каждую операцию
// Формат: "borrow [userID] [bookID]" или "return [userID] [bookID]"
for i := 0; i < numOps; i++ {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
parts := strings.Split(line, " ")
// TODO: Разобрать операцию и вызвать соответствующий метод
// Выведите "OK" при успехе или "Error: [message]" при ошибке
}
}
Все уроки раздела Объектно-ориентированное программирование
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 Pool12Продвинутые концепции ООП
Паттерн функциональных опцийПаттерн Builder в GoЦепочки вызовов методовПсевдонимы и определения типовОсновы рефлексииОбзор генерации кода15Проект: Управление библиотекой
Обзор и структура проектаСтруктуры Book и UserПотренируйтесь самостоятельно: Онлайн-компилятор Go