Веб-разработка на Go
Теория: CRUD-операции в Fiber
В этом уроке мы научимся разрабатывать веб-приложение, которое выполняет различные операции над данными в хранилище: создание, чтение, обновление и удаление. Для веб-разработки это важная тема, потому что почти все веб-приложения выполняют эти операции.
Представим, что вам нужно разработать систему управления сотрудников компании. Если вы неправильно организуете операции для работы с пользователями, то вам и вашим коллегам будет тяжело поддерживать и развивать систему.
CRUD-операции
Любой объект в хранилище можно представить в виде ресурса. С ресурсом можно работать посредством следующих операций:
- Создание — create
- Чтение — read
- Обновление — update
- Удаление — delete
По первым буквам английских названий этих операций образуется акроним CRUD. Так как в веб-приложениях взаимодействие происходит по HTTP, нужно сопоставить операции CRUD с этим протоколом. Обычно для каждой операции используют свой HTTP-метод:
- C (create) — POST
- R (read) — GET
- U (update) — PATCH/PUT
- D (delete) — DELETE
Например, мы разрабатываем систему управления сотрудников компании. Ресурс в данной системе — сотрудник. Путь до него мы определяем как /employees, а CRUD будет выглядеть следующим образом:
- C (create) — POST /employees
- R (read) — GET /employees или GET /employees/
- U (update) — PATCH/PUT /employees/
- D (delete) — DELETE /employees/
Каждый метод содержит идентификатор сотрудника, кроме метода создания. Это связано с тем, что когда сотрудник создается, его еще нет в хранилище. Поэтому его идентификатор неизвестен.
Мы определили, как будут выглядеть CRUD-операции на протоколе HTTP. Теперь рассмотрим, как реализовать это в микрофреймворке Fiber.
CRUD-операции в Fiber
В Fiber каждый HTTP-метод представлен своей функцией. Чтобы реализовать CRUD-операции в веб-приложении, мы будем использовать следующие функции:
Для каждой CRUD-операции описывается уникальный обработчик. Каждый обработчик выполняет конкретную маленькую задачу и не должен содержать в себе логики, которая не относится к этой операции. Такое построение веб-приложения позволит легко масштабировать и поддерживать код.
Для простоты представим, что объект сотрудника содержит только идентификатор, электронную почту и роль. Хранить данные будем в оперативной памяти приложения с помощью структуры данных map:
Разберем каждую CRUD-операцию подробнее.
Создание сотрудника
Изначально в хранилище нет сотрудников, поэтому первым делом нам нужно реализовать метод его создания. Для этого используется метод POST /employees, в котором передаются все данные нового сотрудника:
Запускаем веб-приложение и отправляем запрос на создание нового сотрудника:
В ответ получаем идентификатор созданного сотрудника:
Мы отправили POST /employees запрос с данными нового сотрудника. Веб-приложение определило обработчик этого запроса, прочитало тело запроса и сохранило данные нового сотрудника в оперативной памяти. В методе создания нового сотрудника в хранилище storage.Create() генерируется идентификатор сотрудника, по которому в будущем будет происходить поиск сотрудника в хранилище.
Идентификатор сотрудника представлен в виде UUID — универсальный уникальный идентификатор. Это гарантирует, что идентификаторы не будут повторяться при большом количестве сотрудников. Генерация UUID стандартизирована, и в Go есть готовая библиотека для генерации такого идентификатора. Для этого используется функция uuid.New().String().
Мы можем создавать сотрудников, но пока не можем получить то, что мы создали. Чтобы решить этот недочет, нам нужен метод чтения.
Чтение данных сотрудников
Метод чтения разделяется на два типа:
- Получение всех сотрудников. Для этого используется метод
GET /employees - Получение конкретного сотрудника. Для этого используется метод
GET /employees/:id, где:id— это идентификатор сотрудника
Для этих операций мы описываем новые объекты ответов:
Также мы добавляем две функции в хранилище, чтобы получить данные сотрудников:
Запускаем веб-приложения и попробуем прочесть данные. Чтобы протестировать получение сотрудников, нам нужно сначала создать пару записей:
На запросы получаем ответы соответственно:
Теперь попробуем получить список всех сотрудников:
Также проверим метод получения одного сотрудника:
Мы реализовали обработчик запросов на чтение данных сотрудников. Когда мы отправили запрос GET /employees, веб-приложение определило обработчик и вернуло все записи из хранилища в JSON-виде.
Если указать идентификатор сотрудника при запросе GET /employees/:id, то веб-приложение вернет данные только одного сотрудника. Мы также учли, что в хранилище может не существовать сотрудник с таким идентификатором. В этом случае веб-приложение вернет ошибку 404.
Обновление сотрудника
Мы научились создавать и читать данные сотрудников, но пока не умеем их обновлять. Например, сотрудник может перейти на другую должность в компании. В этом случае будет отправляться запрос на обновление PATCH /employees/:id с новым значением поля Role.
Реализуем обработчик обновления. Начнем с описания запроса на обновление:
Теперь опишем обработчик запроса на обновление:
Далее опишем метод обновления сотрудника в хранилище:
Запускаем веб-приложение и создаем нового сотрудника:
Теперь обновим данные этого сотрудника:
В ответе получаем пустую строку с кодом 204 No Content, что означает — запрос обработан успешно.
Попробуем получить данные этого сотрудника:
И мы видим, что данные сотрудника обновились:
Когда мы отправили запрос на обновление PATCH /employees/:id, веб-приложение верно определило обработчик, нашло сотрудника по идентификатору и обновило его данные в хранилище.
Таким образом мы написали почти все операции над ресурсом employees. Осталось только реализовать удаление сотрудника.
Удаление сотрудника
Со временем сотрудники могут увольняться из компании. В этом случае у нас должен быть метод удаления сотрудника из хранилища. Удаление происходит с помощью метода DELETE /employees/:id, где :id — это идентификатор сотрудника.
Для начала опишем функцию удаления сотрудника из хранилища. В нашем случае она состоит из одной строки:
Теперь добавим обработчик для метода DELETE /employees/:id:
Запускаем веб-приложения и создаем нового сотрудника:
В ответ получаем идентификатор сотрудника:
Теперь проверим метод удаления:
Запрос не вернул ошибку, и это значит, что он прошел успешно. Попробуем получить данные удаленного сотрудника:
В ответ получаем ожидаемую ошибку, что сотрудник не найден:
Таким образом мы реализовали последнюю CRUD-операцию — удаление сотрудника. Когда мы отправили запрос DELETE /employees/:id, веб-приложение по идентификатору удалило сотрудника из хранилища.
Выводы
В этом уроке мы научились разрабатывать веб-приложение, которое выполняет различные операции над данными в хранилище. Повторим важные моменты темы:
- CRUD — это аббревиатура, которая означает Create, Read, Update, Delete
- Построение веб-приложений по CRUD-модели распространено благодаря простоте разработки и поддержки кода
- Со стороны HTTP-протокола CRUD-модель реализуется с помощью методов GET, POST, PATCH/PUT, DELETE
