CLI-интерфейс администратора
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 103 из 107.
Задание
ЛегкоДавайте создадим интерфейс командной строки для нашей системы управления библиотекой с помощью паттерна «Команда»! Вы создадите CLI, который обрабатывает административные команды, такие как добавление книг, регистрация пользователей и управление операциями заимствования — всё это благодаря чистой, расширяемой архитектуре.
Вы организуете код в шести файлах:
book.go: ваша структураBookс JSON-тегами дляID,Title,Author,ISBNиAvailable. Добавьте конструкторNewBook.user.go: ваша структураUserс JSON-тегами дляID,Name,EmailиBorrowedBooks. Добавьте конструкторNewUser.library.go: ваша структураLibraryс отображениями для книг и пользователей, а также методамиAddBook,AddUser,BorrowиReturnиз предыдущих уроков.commands.go: здесь паттерн «Команда» воплощается в жизнь! Определите интерфейсCommandс методомExecute, который принимает*Libraryи аргументы[]string, возвращая строковый результат. Затем реализуйте следующие структуры команд:AddBookCommand: ожидает 4 аргумента: id, title, author, isbn. Добавляет книгу и возвращаетBook added: [title]AddUserCommand: ожидает 3 аргумента: id, name, email. Добавляет пользователя и возвращаетUser added: [name]BorrowCommand: ожидает 2 аргумента: userID, bookID. При успешном выполнении возвращаетBorrowed: [bookID], а при ошибке —Error: [message]ReturnCommand: ожидает 2 аргумента: userID, bookID. При успешном выполнении возвращаетReturned: [bookID], а при ошибке —Error: [message]ListBooksCommand: не принимает аргументов. Возвращает ID и название каждой книги на отдельных строках в формате[id]: [title]илиNo books, если список пуст (книги должны быть отсортированы по ID)
Если команда получает недостаточно аргументов, верните
Error: insufficient argumentscli.go: создайте структуруCLI, которая хранит указатель наLibraryи отображение имён команд на реализации интерфейсаCommand. Реализуйте:- конструктор
NewCLI, который инициализирует CLI с библиотекой и регистрирует все команды:addbook,adduser,borrow,return,listbooks - метод
Run, который принимает строку ввода, разбирает её с помощьюstrings.Fields, находит команду и выполняет её. Для пустого ввода вернитеNo command provided, а для неизвестных команд —Unknown command: [name]
- конструктор
main.go: создайте библиотеку и CLI, затем обрабатывайте команды из ввода. Сначала прочитайте количество команд, затем считывайте каждую строку команды отдельно. Для каждой команды вызовитеRunи выведите результат.
Будут предоставлены следующие входные данные:
- Количество команд
- Каждая команда в виде полной строки на отдельной строке
Например, для ввода:
6
addbook B001 Go-Programming Alan-Donovan 978-0134190440
addbook B002 Clean-Code Robert-Martin 978-0132350884
adduser U001 Alice alice@test.com
borrow U001 B001
listbooks
borrow U001 B001Ваш вывод должен быть таким:
Book added: Go-Programming
Book added: Clean-Code
User added: Alice
Borrowed: B001
B001: Go-Programming
B002: Clean-Code
Error: book not availableА для ввода:
4
listbooks
addbook B100 Design-Patterns Gang-of-Four 978-0201633610
listbooks
invalidcmd testВаш вывод должен быть таким:
No books
Book added: Design-Patterns
B100: Design-Patterns
Unknown command: invalidcmdА для ввода:
5
adduser U001 Bob bob@email.com
borrow U001 B001
addbook B001 Golang-Guide John-Smith 123-456
borrow U001 B001
return U001 B001Ваш вывод должен быть таким:
User added: Bob
Error: book not found
Book added: Golang-Guide
Borrowed: B001
Returned: B001Обратите внимание: CLI не нужно знать детали каждой операции. Он просто находит команду и делегирует ей выполнение. Благодаря этому добавление новых команд сводится к созданию новой структуры, реализующей интерфейс Command, и её регистрации в CLI!
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// Прочитать количество команд
var n int
fmt.Scanln(&n)
// Создать сканер для чтения полных строк
scanner := bufio.NewScanner(os.Stdin)
// TODO: Создать новую Library
// TODO: Создать новый CLI с library
// TODO: Обработать каждую команду
// Для каждой из n команд:
// - Прочитать строку команды с помощью scanner.Scan() и scanner.Text()
// - Выполнить команду через CLI
// - Вывести результат
_ = scanner // Удалите эту строку, когда будете использовать scanner
}
Все уроки раздела Объектно-ориентированное программирование
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