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>