Let's Go استفاده از زمینه درخواست › چگونه زمینه درخواست کار می‌کند
قبلی · فهرست · بعدی
فصل ۱۱.۱.

نحوه عملکرد زمینه درخواست (How Request Context Works)

در این بخش، نحوه عملکرد زمینه درخواست (Request Context) را بررسی می‌کنیم. این شامل مدیریت داده‌ها (Data Management)، انتشار سیگنال (Signal Propagation) و زمان‌بندی (Timing) می‌شود.

برای شروع، بیایید با مفاهیم پایه (Basic Concepts) زمینه درخواست آشنا شویم:

هر http.Request که میان‌افزار و هندلرهای ما پردازش می‌کنند، یک شیء context.Context در خود دارد که می‌توانیم از آن برای ذخیره اطلاعات در طول عمر درخواست استفاده کنیم.

همانطور که قبلاً اشاره کردم، در یک برنامه وب یک مورد استفاده رایج برای این است که اطلاعات را بین قطعات میان‌افزار و هندلرهای دیگر خود منتقل کنید.

در مورد ما، می‌خواهیم از آن برای بررسی اینکه آیا یک کاربر احراز هویت شده است در برخی از میان‌افزارها استفاده کنیم، و اگر آنها احراز هویت شده‌اند، این اطلاعات را برای همه میان‌افزارها و هندلرهای دیگر خود در دسترس قرار دهیم.

بیایید با کمی تئوری شروع کنیم و نحو کار با زمینه درخواست را توضیح دهیم. سپس، در فصل بعدی، دوباره کمی عملی‌تر خواهیم شد و نشان خواهیم داد که چگونه می‌توان آن را به طور عملی در برنامه خود استفاده کرد.

نحو زمینه درخواست

کد پایه برای افزودن اطلاعات به زمینه یک درخواست به این صورت است:

// Where r is a *http.Request...
ctx := r.Context()
ctx = context.WithValue(ctx, "isAuthenticated", true)
r = r.WithContext(ctx)

بیایید این را خط به خط بررسی کنیم.

همچنین باید اشاره کنم که، برای وضوح، آن قطعه کد را کمی بیشتر از آنچه که نیاز بود، مفصل کردم. معمولاً به این صورت نوشته می‌شود:

ctx = context.WithValue(r.Context(), "isAuthenticated", true)
r = r.WithContext(ctx)

پس اینگونه است که داده‌ها را به زمینه یک درخواست اضافه می‌کنید. اما چگونه می‌توان آن را دوباره بازیابی کرد؟

نکته مهمی که باید توضیح دهم این است که، در پشت صحنه، مقادیر زمینه درخواست با نوع any ذخیره می‌شوند. و این بدان معناست که، پس از بازیابی آنها از زمینه، باید آنها را به نوع اصلی خود قبل از استفاده از آنها تبدیل کنید.

برای بازیابی یک مقدار باید از روش r.Context().Value() استفاده کنیم، به این صورت:

isAuthenticated, ok := r.Context().Value("isAuthenticated").(bool)
if !ok {
    return errors.New("could not convert value to bool")
}

اجتناب از برخورد کلیدها

در نمونه‌های کد بالا، من از رشته "isAuthenticated" به عنوان کلید برای ذخیره و بازیابی داده‌ها از زمینه یک درخواست استفاده کرده‌ام. اما این توصیه نمی‌شود زیرا خطر این وجود دارد که بسته‌های شخص ثالث دیگری که توسط برنامه شما استفاده می‌شوند نیز بخواهند داده‌ها را با استفاده از کلید "isAuthenticated" ذخیره کنند — و این باعث برخورد نام‌گذاری می‌شود.

برای اجتناب از این، بهتر است نوع سفارشی خود را ایجاد کنید که می‌توانید از آن برای کلیدهای زمینه خود استفاده کنید. با گسترش کد نمونه ما، بهتر است چیزی شبیه به این انجام دهید:

// Declare a custom "contextKey" type for your context keys.
type contextKey string

// Create a constant with the type contextKey that we can use.
const isAuthenticatedContextKey = contextKey("isAuthenticated")

...

// Set the value in the request context, using our isAuthenticatedContextKey 
// constant as the key.
ctx := r.Context()
ctx = context.WithValue(ctx, isAuthenticatedContextKey, true)
r = r.WithContext(ctx)

...

// Retrieve the value from the request context using our constant as the key.
isAuthenticated, ok := r.Context().Value(isAuthenticatedContextKey).(bool)
if !ok {
    return errors.New("could not convert value to bool")
}

واژه‌نامه اصطلاحات فنی

اصطلاح فارسی معادل انگلیسی توضیح
زمینه درخواست Request Context محیط اجرای درخواست
مدیریت داده‌ها Data Management کنترل داده‌های درخواست
انتشار سیگنال Signal Propagation ارسال سیگنال در برنامه
زمان‌بندی Timing کنترل زمان اجرا
مفاهیم پایه Basic Concepts اصول اولیه
درخت زمینه Context Tree ساختار سلسله مراتبی زمینه
مقدار کلید Key Value داده ذخیره شده در زمینه
کانال لغو Cancel Channel کانال ارتباطی لغو عملیات
مهلت زمانی Timeout محدودیت زمان اجرا
همگام‌سازی Synchronization هماهنگی اجرای عملیات