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с картами (maps) для книг и пользователей, а также методамиAddBook,AddUser,BorrowиReturnиз предыдущих уроков.commands.go: Здесь паттерн «Команда» оживает! Определите интерфейсCommandс методомExecute, который принимает*Libraryи аргументы[]string, возвращая строковый результат. Затем реализуйте следующие структуры команд:AddBookCommand— ожидает 4 аргумента: id, title, author, isbn. Добавляет книгу и возвращает"Book added: " + book.TitleAddUserCommand— ожидает 3 аргумента: id, name, email. Добавляет пользователя и возвращает"User added: " + user.NameBorrowCommand— ожидает 2 аргумента: userID, bookID. Возвращает"Borrowed: " + args[1]в случае успеха или"Error: " + err.Error()в случае ошибкиReturnCommand— ожидает 2 аргумента: userID, bookID. Возвращает"Returned: " + args[1]в случае успеха или"Error: " + err.Error()в случае ошибкиListBooksCommand— не принимает аргументов. Возвращает ID и название каждой книги на отдельных строках в формате[id]: [title]или"No books", если список пуст (список книг должен быть отсортирован по ID)
Если команда получает недостаточное количество аргументов, верните
"Error: insufficient arguments"cli.go: Создайте структуруCLI, которая содержит указатель наLibraryи карту соответствия имен команд реализациямCommand. Создайте:- Конструктор
NewCLI, который инициализирует CLI библиотекой и регистрирует все команды:"addbook","adduser","borrow","return","listbooks" - Метод
Run, который принимает входную строку, разбирает ее с помощьюstrings.Fields, ищет команду и выполняет ее. Возвращает"No command provided"для пустого ввода или"Unknown command: " + parts[0]для нераспознанных команд
- Конструктор
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: Создать новую библиотеку
// TODO: Создать новый CLI с библиотекой
// TODO: Обработать каждую команду
// Для каждой из n команд:
// - Прочитать командную строку, используя scanner.Scan() и scanner.Text()
// - Запустить команду через CLI
// - Вывести результат
_ = 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