История расскажет, что такое контекст, как вы можете его использовать и почему вы должны его использовать. Вы получите полезные знания по теме, а не очередную большую статью о том, почему вам не стоит ее использовать, или о каких-то магических подходах к контексту.
Каков контекст?
Вы можете думать о контексте как об одном менеджере, который контролирует всех сотрудников. Менеджер мало что знает о работе, но он может сказать всем сотрудникам, чтобы они остановились, таков контекст. Более того, в контексте могут храниться пары «ключ-значение» полезных данных, которыми можно делиться через ваше приложение.
Первый пример собственного контекста
Это простейший контекст, который вы можете создать в go. По сути, он «ловит» контекст, который работает в фоне данной части кода. Это.
Затем во внутренних частях приложения вы можете «прослушать» выполняемый контекст, то есть в каком-то цикле for с оператором select. Проверьте приведенный ниже пример.
Код довольно прост. У нас есть функция Parent, которая делает 4 вещи:
- Создает контекст из фона
- Создает группу ожидания, используемую для синхронизации основной горутины с вновь созданной.
- Выполнение функции Worker в другой горутине
Функция Worker в основном работает в фоновом режиме и ждет сигнала из контекста о том, что задание должно быть выполнено. Все это.
Вы, вероятно, думаете о том, как мы можем отправить сигнал Done через контекст. Нет ничего проще, посмотрите пример, это просто расширенная версия предыдущего
Как видите, в функцию Родительский внесены лишь небольшие изменения. Мы изменили контекст по умолчанию на расширенную версию: context.WithCancel. Эта функция возвращает тот же контекст, что и выше, с еще одной функцией, отмена. Отмена может быть вызвана в разных местах, чтобы сигнализировать о состоянии контекста «готово». Мы вызываем его в другой горутине через 500 мс. Затем он остановит выполнение функции Worker.
Контекст в HTTP API
Контекст является частью HTTP-запроса в функциях-обработчиках по умолчанию.
Как видите, вы можете использовать метод r.Context(), чтобы получить текущий контекст запроса и передать его в кроличью нору. Вы можете спросить, почему? Ну, ответ довольно прост, скажем, fetchExistingPosts выполняется около 4 секунд. Вызывающий AddMediumPost не терпит и останавливает запрос через 1 с. Есть еще 3 секунды работы, которую нужно сделать впустую. Вот контекст, в основном функция отмены вызывается всякий раз, когда вызывающий объект AddMediumPost завершается слишком рано, и с учетом сказанного вся работа в fetchExistingPosts также может быть выполнена, а некоторые ресурсы могут быть сохранены для другого задания.
Полезные советы
Почти всегда используйте контекст в функциях/методах
При этом почти всегда используйте контекст в качестве первого параметра функции/метода, даже если в данный момент он там не нужен. Это правило применимо почти ко всем функциям длиной более 20 строк, потому что есть большая вероятность, что вам понадобится контекст в будущем, и поверьте мне, добавление его по всему дереву вызывающих функций — очень долгая работа. Если он вам не нужен в данный момент, вы всегда можете объявить его как пол:
func SomeFunction(_ context.Context) ошибка {}
Не передавайте его в поля структуры
Звучит как хорошая идея передать его в структуру, а затем повторно использовать во множестве различных методов без необходимости повторения контекста первого параметра. Но это неправильно. Вы можете использовать одну и ту же структуру во многих разных местах, используя разные контексты. Было бы очень сложно передать разные контексты этой вещи.
Вот и все
Спасибо за прочтение. Я хотел передать вам некоторые полезные знания и советы, чтобы упростить вашу работу с вашим кодом golang. Если у вас есть вопросы, задавайте их в комментариях, и я сразу отвечу на них. Увидимся в следующий раз!