HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>В этом уроке мы научимся разрабатывать веб-приложение, которое выполняет различные операции над данными в хранилище: создание, чтение, обновление и удаление. Для веб-разработки это важная тема, потому что почти все веб-приложения выполняют эти операции.</p>
1 <p>В этом уроке мы научимся разрабатывать веб-приложение, которое выполняет различные операции над данными в хранилище: создание, чтение, обновление и удаление. Для веб-разработки это важная тема, потому что почти все веб-приложения выполняют эти операции.</p>
2 <p>Представим, что вам нужно разработать систему управления сотрудников компании. Если вы неправильно организуете операции для работы с пользователями, то вам и вашим коллегам будет тяжело поддерживать и развивать систему.</p>
2 <p>Представим, что вам нужно разработать систему управления сотрудников компании. Если вы неправильно организуете операции для работы с пользователями, то вам и вашим коллегам будет тяжело поддерживать и развивать систему.</p>
3 <h2>CRUD-операции</h2>
3 <h2>CRUD-операции</h2>
4 <p>Любой объект в хранилище можно представить в виде ресурса. С ресурсом можно работать посредством следующих операций:</p>
4 <p>Любой объект в хранилище можно представить в виде ресурса. С ресурсом можно работать посредством следующих операций:</p>
5 <ul><li>Создание - create</li>
5 <ul><li>Создание - create</li>
6 <li>Чтение - read</li>
6 <li>Чтение - read</li>
7 <li>Обновление - update</li>
7 <li>Обновление - update</li>
8 <li>Удаление - delete</li>
8 <li>Удаление - delete</li>
9 </ul><p>По первым буквам английских названий этих операций образуется акроним CRUD. Так как в веб-приложениях взаимодействие происходит по HTTP, нужно сопоставить операции CRUD с этим протоколом. Обычно для каждой операции используют свой HTTP-метод:</p>
9 </ul><p>По первым буквам английских названий этих операций образуется акроним CRUD. Так как в веб-приложениях взаимодействие происходит по HTTP, нужно сопоставить операции CRUD с этим протоколом. Обычно для каждой операции используют свой HTTP-метод:</p>
10 <ul><li>C (create) - POST</li>
10 <ul><li>C (create) - POST</li>
11 <li>R (read) - GET</li>
11 <li>R (read) - GET</li>
12 <li>U (update) - PATCH/PUT</li>
12 <li>U (update) - PATCH/PUT</li>
13 <li>D (delete) - DELETE</li>
13 <li>D (delete) - DELETE</li>
14 </ul><p>Например, мы разрабатываем систему управления сотрудников компании. Ресурс в данной системе - сотрудник. Путь до него мы определяем как /employees, а CRUD будет выглядеть следующим образом:</p>
14 </ul><p>Например, мы разрабатываем систему управления сотрудников компании. Ресурс в данной системе - сотрудник. Путь до него мы определяем как /employees, а CRUD будет выглядеть следующим образом:</p>
15 <ul><li>C (create) - POST /employees</li>
15 <ul><li>C (create) - POST /employees</li>
16 <li>R (read) - GET /employees или GET /employees/</li>
16 <li>R (read) - GET /employees или GET /employees/</li>
17 <li>U (update) - PATCH/PUT /employees/</li>
17 <li>U (update) - PATCH/PUT /employees/</li>
18 <li>D (delete) - DELETE /employees/</li>
18 <li>D (delete) - DELETE /employees/</li>
19 </ul><p>Каждый метод содержит идентификатор сотрудника, кроме метода создания. Это связано с тем, что когда сотрудник создается, его еще нет в хранилище. Поэтому его идентификатор неизвестен.</p>
19 </ul><p>Каждый метод содержит идентификатор сотрудника, кроме метода создания. Это связано с тем, что когда сотрудник создается, его еще нет в хранилище. Поэтому его идентификатор неизвестен.</p>
20 <p>Мы определили, как будут выглядеть CRUD-операции на протоколе HTTP. Теперь рассмотрим, как реализовать это в микрофреймворке Fiber.</p>
20 <p>Мы определили, как будут выглядеть CRUD-операции на протоколе HTTP. Теперь рассмотрим, как реализовать это в микрофреймворке Fiber.</p>
21 <h2>CRUD-операции в Fiber</h2>
21 <h2>CRUD-операции в Fiber</h2>
22 <p>В Fiber каждый HTTP-метод представлен своей функцией. Чтобы реализовать CRUD-операции в веб-приложении, мы будем использовать следующие функции:</p>
22 <p>В Fiber каждый HTTP-метод представлен своей функцией. Чтобы реализовать CRUD-операции в веб-приложении, мы будем использовать следующие функции:</p>
23 <p>Для каждой CRUD-операции описывается уникальный обработчик. Каждый обработчик выполняет конкретную маленькую задачу и не должен содержать в себе логики, которая не относится к этой операции. Такое построение веб-приложения позволит легко масштабировать и поддерживать код.</p>
23 <p>Для каждой CRUD-операции описывается уникальный обработчик. Каждый обработчик выполняет конкретную маленькую задачу и не должен содержать в себе логики, которая не относится к этой операции. Такое построение веб-приложения позволит легко масштабировать и поддерживать код.</p>
24 <p>Для простоты представим, что объект сотрудника содержит только идентификатор, электронную почту и роль. Хранить данные будем в оперативной памяти приложения с помощью структуры данных<em>map</em>:</p>
24 <p>Для простоты представим, что объект сотрудника содержит только идентификатор, электронную почту и роль. Хранить данные будем в оперативной памяти приложения с помощью структуры данных<em>map</em>:</p>
25 <p>Разберем каждую CRUD-операцию подробнее.</p>
25 <p>Разберем каждую CRUD-операцию подробнее.</p>
26 <h3>Создание сотрудника</h3>
26 <h3>Создание сотрудника</h3>
27 <p>Изначально в хранилище нет сотрудников, поэтому первым делом нам нужно реализовать метод его создания. Для этого используется метод POST /employees, в котором передаются все данные нового сотрудника:</p>
27 <p>Изначально в хранилище нет сотрудников, поэтому первым делом нам нужно реализовать метод его создания. Для этого используется метод POST /employees, в котором передаются все данные нового сотрудника:</p>
28 <p>Запускаем веб-приложение и отправляем запрос на создание нового сотрудника:</p>
28 <p>Запускаем веб-приложение и отправляем запрос на создание нового сотрудника:</p>
29 <p>В ответ получаем идентификатор созданного сотрудника:</p>
29 <p>В ответ получаем идентификатор созданного сотрудника:</p>
30 <p>Мы отправили POST /employees запрос с данными нового сотрудника. Веб-приложение определило обработчик этого запроса, прочитало тело запроса и сохранило данные нового сотрудника в оперативной памяти. В методе создания нового сотрудника в хранилище storage.Create() генерируется идентификатор сотрудника, по которому в будущем будет происходить поиск сотрудника в хранилище.</p>
30 <p>Мы отправили POST /employees запрос с данными нового сотрудника. Веб-приложение определило обработчик этого запроса, прочитало тело запроса и сохранило данные нового сотрудника в оперативной памяти. В методе создания нового сотрудника в хранилище storage.Create() генерируется идентификатор сотрудника, по которому в будущем будет происходить поиск сотрудника в хранилище.</p>
31 <p>Идентификатор сотрудника представлен в виде<strong>UUID</strong>- универсальный уникальный идентификатор. Это гарантирует, что идентификаторы не будут повторяться при большом количестве сотрудников. Генерация UUID стандартизирована, и в Go есть готовая библиотека для генерации такого идентификатора. Для этого используется функция uuid.New().String().</p>
31 <p>Идентификатор сотрудника представлен в виде<strong>UUID</strong>- универсальный уникальный идентификатор. Это гарантирует, что идентификаторы не будут повторяться при большом количестве сотрудников. Генерация UUID стандартизирована, и в Go есть готовая библиотека для генерации такого идентификатора. Для этого используется функция uuid.New().String().</p>
32 <p>Мы можем создавать сотрудников, но пока не можем получить то, что мы создали. Чтобы решить этот недочет, нам нужен метод чтения.</p>
32 <p>Мы можем создавать сотрудников, но пока не можем получить то, что мы создали. Чтобы решить этот недочет, нам нужен метод чтения.</p>
33 <h3>Чтение данных сотрудников</h3>
33 <h3>Чтение данных сотрудников</h3>
34 <p>Метод чтения разделяется на два типа:</p>
34 <p>Метод чтения разделяется на два типа:</p>
35 <ul><li>Получение всех сотрудников. Для этого используется метод GET /employees</li>
35 <ul><li>Получение всех сотрудников. Для этого используется метод GET /employees</li>
36 <li>Получение конкретного сотрудника. Для этого используется метод GET /employees/:id, где :id - это идентификатор сотрудника</li>
36 <li>Получение конкретного сотрудника. Для этого используется метод GET /employees/:id, где :id - это идентификатор сотрудника</li>
37 </ul><p>Для этих операций мы описываем новые объекты ответов:</p>
37 </ul><p>Для этих операций мы описываем новые объекты ответов:</p>
38 <p>Также мы добавляем две функции в хранилище, чтобы получить данные сотрудников:</p>
38 <p>Также мы добавляем две функции в хранилище, чтобы получить данные сотрудников:</p>
39 <p>Запускаем веб-приложения и попробуем прочесть данные. Чтобы протестировать получение сотрудников, нам нужно сначала создать пару записей:</p>
39 <p>Запускаем веб-приложения и попробуем прочесть данные. Чтобы протестировать получение сотрудников, нам нужно сначала создать пару записей:</p>
40 <p>На запросы получаем ответы соответственно:</p>
40 <p>На запросы получаем ответы соответственно:</p>
41 <p>Теперь попробуем получить список всех сотрудников:</p>
41 <p>Теперь попробуем получить список всех сотрудников:</p>
42 <p>Также проверим метод получения одного сотрудника:</p>
42 <p>Также проверим метод получения одного сотрудника:</p>
43 <p>Мы реализовали обработчик запросов на чтение данных сотрудников. Когда мы отправили запрос GET /employees, веб-приложение определило обработчик и вернуло все записи из хранилища в JSON-виде.</p>
43 <p>Мы реализовали обработчик запросов на чтение данных сотрудников. Когда мы отправили запрос GET /employees, веб-приложение определило обработчик и вернуло все записи из хранилища в JSON-виде.</p>
44 <p>Если указать идентификатор сотрудника при запросе GET /employees/:id, то веб-приложение вернет данные только одного сотрудника. Мы также учли, что в хранилище может не существовать сотрудник с таким идентификатором. В этом случае веб-приложение вернет ошибку 404.</p>
44 <p>Если указать идентификатор сотрудника при запросе GET /employees/:id, то веб-приложение вернет данные только одного сотрудника. Мы также учли, что в хранилище может не существовать сотрудник с таким идентификатором. В этом случае веб-приложение вернет ошибку 404.</p>
45 <h3>Обновление сотрудника</h3>
45 <h3>Обновление сотрудника</h3>
46 <p>Мы научились создавать и читать данные сотрудников, но пока не умеем их обновлять. Например, сотрудник может перейти на другую должность в компании. В этом случае будет отправляться запрос на обновление PATCH /employees/:id с новым значением поля Role.</p>
46 <p>Мы научились создавать и читать данные сотрудников, но пока не умеем их обновлять. Например, сотрудник может перейти на другую должность в компании. В этом случае будет отправляться запрос на обновление PATCH /employees/:id с новым значением поля Role.</p>
47 <p>Реализуем обработчик обновления. Начнем с описания запроса на обновление:</p>
47 <p>Реализуем обработчик обновления. Начнем с описания запроса на обновление:</p>
48 <p>Теперь опишем обработчик запроса на обновление:</p>
48 <p>Теперь опишем обработчик запроса на обновление:</p>
49 <p>Далее опишем метод обновления сотрудника в хранилище:</p>
49 <p>Далее опишем метод обновления сотрудника в хранилище:</p>
50 <p>Запускаем веб-приложение и создаем нового сотрудника:</p>
50 <p>Запускаем веб-приложение и создаем нового сотрудника:</p>
51 <p>Теперь обновим данные этого сотрудника:</p>
51 <p>Теперь обновим данные этого сотрудника:</p>
52 <p>В ответе получаем пустую строку с кодом 204 No Content, что означает - запрос обработан успешно.</p>
52 <p>В ответе получаем пустую строку с кодом 204 No Content, что означает - запрос обработан успешно.</p>
53 <p>Попробуем получить данные этого сотрудника:</p>
53 <p>Попробуем получить данные этого сотрудника:</p>
54 <p>И мы видим, что данные сотрудника обновились:</p>
54 <p>И мы видим, что данные сотрудника обновились:</p>
55 <p>Когда мы отправили запрос на обновление PATCH /employees/:id, веб-приложение верно определило обработчик, нашло сотрудника по идентификатору и обновило его данные в хранилище.</p>
55 <p>Когда мы отправили запрос на обновление PATCH /employees/:id, веб-приложение верно определило обработчик, нашло сотрудника по идентификатору и обновило его данные в хранилище.</p>
56 <p>Таким образом мы написали почти все операции над ресурсом employees. Осталось только реализовать удаление сотрудника.</p>
56 <p>Таким образом мы написали почти все операции над ресурсом employees. Осталось только реализовать удаление сотрудника.</p>
57 <h3>Удаление сотрудника</h3>
57 <h3>Удаление сотрудника</h3>
58 <p>Со временем сотрудники могут увольняться из компании. В этом случае у нас должен быть метод удаления сотрудника из хранилища. Удаление происходит с помощью метода DELETE /employees/:id, где :id - это идентификатор сотрудника.</p>
58 <p>Со временем сотрудники могут увольняться из компании. В этом случае у нас должен быть метод удаления сотрудника из хранилища. Удаление происходит с помощью метода DELETE /employees/:id, где :id - это идентификатор сотрудника.</p>
59 <p>Для начала опишем функцию удаления сотрудника из хранилища. В нашем случае она состоит из одной строки:</p>
59 <p>Для начала опишем функцию удаления сотрудника из хранилища. В нашем случае она состоит из одной строки:</p>
60 <p>Теперь добавим обработчик для метода DELETE /employees/:id:</p>
60 <p>Теперь добавим обработчик для метода DELETE /employees/:id:</p>
61 <p>Запускаем веб-приложения и создаем нового сотрудника:</p>
61 <p>Запускаем веб-приложения и создаем нового сотрудника:</p>
62 <p>В ответ получаем идентификатор сотрудника:</p>
62 <p>В ответ получаем идентификатор сотрудника:</p>
63 <p>Теперь проверим метод удаления:</p>
63 <p>Теперь проверим метод удаления:</p>
64 <p>Запрос не вернул ошибку, и это значит, что он прошел успешно. Попробуем получить данные удаленного сотрудника:</p>
64 <p>Запрос не вернул ошибку, и это значит, что он прошел успешно. Попробуем получить данные удаленного сотрудника:</p>
65 <p>В ответ получаем ожидаемую ошибку, что сотрудник не найден:</p>
65 <p>В ответ получаем ожидаемую ошибку, что сотрудник не найден:</p>
66 <p>Таким образом мы реализовали последнюю CRUD-операцию - удаление сотрудника. Когда мы отправили запрос DELETE /employees/:id, веб-приложение по идентификатору удалило сотрудника из хранилища.</p>
66 <p>Таким образом мы реализовали последнюю CRUD-операцию - удаление сотрудника. Когда мы отправили запрос DELETE /employees/:id, веб-приложение по идентификатору удалило сотрудника из хранилища.</p>
67 <h2>Выводы</h2>
67 <h2>Выводы</h2>
68 <p>В этом уроке мы научились разрабатывать веб-приложение, которое выполняет различные операции над данными в хранилище. Повторим важные моменты темы:</p>
68 <p>В этом уроке мы научились разрабатывать веб-приложение, которое выполняет различные операции над данными в хранилище. Повторим важные моменты темы:</p>
69 <ul><li>CRUD - это аббревиатура, которая означает Create, Read, Update, Delete</li>
69 <ul><li>CRUD - это аббревиатура, которая означает Create, Read, Update, Delete</li>
70 <li>Построение веб-приложений по CRUD-модели распространено благодаря простоте разработки и поддержки кода</li>
70 <li>Построение веб-приложений по CRUD-модели распространено благодаря простоте разработки и поддержки кода</li>
71 <li>Со стороны HTTP-протокола CRUD-модель реализуется с помощью методов GET, POST, PATCH/PUT, DELETE</li>
71 <li>Со стороны HTTP-протокола CRUD-модель реализуется с помощью методов GET, POST, PATCH/PUT, DELETE</li>
72 </ul>
72 </ul>