Базовое пошаговое руководство…
Начиная с того, что такое Context, Context - это тип в Go, который включен в пакет context. У контекста есть тайм-аут, отмены, значения области запроса, которые передаются от одного метода к другому, включая запросы сервера БД.
Входящие запросы API должны содержать родительский контекст, который затем передается промежуточным методам перед возвратом ответа.
Мы можем создать производный (настраиваемый) контекст с использованием родительского контекста с заменой значений по умолчанию. Когда контекст отменяется, все производные от него контексты отменяются.
В GO контекст играет важную роль при использовании подпрограмм го. один и тот же контекст может использоваться несколькими подпрограммами go, а также метод cancel () контекста может быть вызван подпрограммами go одновременно. мы увидим о различных методах в следующей части блога.
Зачем нужен отдельный тип в качестве контекста (хотя у нас есть тип структуры):
Мы не должны использовать настраиваемый тип структуры для контекста, чтобы избежать условий гонки при замене значений с локальной областью.
Давайте рассмотрим пример -
//pseudo code type CustomCtxStruct struct { timeout int } func New() *CustomCtxStruct { return &CustomCtxStruct{timeout: 100} } func (ctx *CustomCtxStruct) hop1() { ctx.timeout // A shared ctx.timeout is used for cancellation, deadlines, and metadata. } func (c *CustomCtxStruct) hop2() { ctx.timeout // A shared ctx.timeout is used for cancellation, deadlines, and metadata. } go hop1() go hop2()
В приведенном выше примере общее значение тайм-аута передается в качестве контекста различным методам hop1 () и hop2 (). Если мы попытаемся заменить здесь значение тайм-аута, специфичное для каждой функции, это может создать условия гонки.
В context.Context эти случаи обрабатываются Mutex, поэтому использование типа Context более безопасно.
Мы должны явно передать контекст каждой функции, которая в нем нуждается. Контекст должен быть первым параметром,
func DoSomething(ctx context.Context, arg Arg) error { // … use ctx … }
Не передавайте нулевой контекст, даже если это разрешено функцией. Передайте context.TODO, если вы не уверены, какой контекст использовать.
Особенности / методы, используемые в контексте:
context.TODO: это пустой контекст, не содержащий значения или временной шкалы. Когда метод не принимает какой-либо объект контекста, но для текущего использования нам нужен некоторый контекст, тогда мы можем инициализировать объект контекста этим.
Если вы работаете внутри своего собственного пакета и у вас нет доступного контекста, в этом случае вам следует использовать контекст TODO или, если есть какие-либо сомнения относительно того, какой контекст вы должны использовать, вы можете использовать контекст TODO.
context.Background: это также возвращает пустой контекст, аналогичный context.TODO, поэтому он никогда не отменяется. Согласно официальной документации, он обычно используется основной функцией, инициализацией и тестами, а также в качестве контекста верхнего уровня для входящих запросов.
вам не следует использовать этот контекст в пакете напрямую; его следует использовать в вашей основной функции. Если вы создаете сервер с пакетом net / http, основной контекст будет предоставлен запросом.
context.WithValue (): этот метод используется для создания производного контекста с ключом и значением.
Ключевые значения относятся к типу interface и должны использоваться только для передачи значений области запроса, а не параметров функции.
func WithValue(parent Context, key, val interface{}) Context
context.WithTimeout (): этот метод используется для создания производного контекста со значением тайм-аута, чтобы сообщить используемой функции, что она должна отменить / остановить свою работу по истечении тайм-аута. По истечении тайм-аута выдает ошибку как - «истек срок контекста».
context.WithDeadline (): этот метод используется для создания производного контекста с определенным временем, которое является крайним сроком для контекста, использующего функцию. Как только время доходит до крайнего срока, он выдает ошибку как - «контекстный крайний срок превышен».
context.WithCancel () - этот метод возвращает производный контекст с копией родительского контекста с каналом Done. Мы должны явно вызвать метод cancel () в этом случае после выполнения функции, в отличие от контекста, созданного методами WithTimeout (), WithDeadline (), метод cancel () вызывается автоматически после достижения условия.
Пример -
Примеры использования распространения контекста и отмены:
Контекст позволяет передавать значения области в методы.
контекст отмены - предположим, что пользователь инициировал запрос, который включает в себя несколько переходов обработки или несколько подпрограмм для выполнения задачи. Между тем, пользователь отменяет запрос, в этом случае мы хотим отменить текущую обработку, а также дочернюю обработку, инициированную для дальнейших переходов. Это отмена всех процессов для продолжения дальнейшей работы называется распространением отмены. Здесь мы можем использовать контекст с отменой.
Для сценариев, когда мы хотим отменить запрос по истечении определенного периода времени ... то есть случаев, когда серверу требуется больше времени для ответа, и мы хотим, чтобы запрос прервался по истечении определенного интервала времени, в этом случае мы можем использовать контекст с таймаутом.
В случаях, когда мы хотим отменить контекст по истечении определенного времени (если мы создаем производный контекст, он проверяет крайний срок для родительского, и если крайний срок уже прошел, он останавливает выполнение), мы должны использовать контекст с крайним сроком.
Разница между gin.context и context.context -
Контекст - самая важная часть структуры джина. Это позволяет нам передавать переменные между промежуточным программным обеспечением, управлять потоком, проверять JSON запроса и, например, отображать ответ JSON.
gin.context похож на оболочку контекста, он реализует все методы контекста, такие как deadline, done, err, value, и имеет свои дополнительные реализации методов.
Метод Copy () пакета контекста gin возвращает копию текущего контекста, которую можно безопасно использовать за пределами области действия запроса. Это должно использоваться, когда контекст должен быть передан в подпрограммы.
Спасибо за чтение !!