ویرگول
ورودثبت نام
Roham
Rohamپیدا کردن خودم توی نوشته ها برام جذابه بهم یه حس خوب بودن می ده مخصوصا وقتی با طعم علم و خلاقیت همراه باشه هر روز که بیشتر با این دنیا آشنا می شم حس بهتری برای بیشتر دونستن و یاد دادن درونم رشد می کنه
Roham
Roham
خواندن ۳ دقیقه·۱ ماه پیش

Context در Golang چیست؟ آموزش کامل + مثال عملی

Context در گولنگ چیست و چگونه به مدیریت کانسل‌کردن، تایم‌اوت و کنترل جریان درخواست‌ها کمک می‌کند
Context در گولنگ چیست و چگونه به مدیریت کانسل‌کردن، تایم‌اوت و کنترل جریان درخواست‌ها کمک می‌کند

مقدمه

در برنامه‌نویسی Go، زمانی که با عملیات هم‌زمان (goroutine)، درخواست‌های شبکه‌ای، اتصال به دیتابیس یا سیستم‌های توزیع‌شده سروکار داریم، باید بتوانیم اجرای یک عملیات را در موقعیت‌های مختلف متوقف یا کنترل کنیم.
Context دقیقاً برای همین هدف ساخته شده است.

در این مقاله به‌صورت کامل و عملی یاد می‌گیرید:

  • Context دقیقاً چیست و چرا وجود دارد؟

  • انواع Context: Background, TODO

  • Context با timeout، deadline، cancel

  • Context برای مدیریت goroutineها

  • ارسال اطلاعات در Context

  • یک مثال کاملاً عملی: API با تایم‌اوت و لغو عملیات


Context در Go چیست؟

Context یک مکانیزم استاندارد در Go است که برای موارد زیر استفاده می‌شود:

۱. لغو (Cancelation) عملیات

وقتی یک درخواست لغو می‌شود، تمام goroutineهای مرتبط با آن باید متوقف شوند.

۲. تنظیم deadline / timeout

برای جلوگیری از بلاک شدن سیستم.

۳. ارسال مقدار (Value Propagation)

اطلاعات سبک (مثل request id) را می‌توان به صورت امن در Context جا‌به‌جا کرد.

۴. مدیریت کارهای وابسته

وقتی والد لغو شود، همه کارهای فرزند نیز لغو می‌شوند.


🔹 Context چگونه کار می‌کند؟

در Go، Context یک interface با ۴ تابع اصلی است:

type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key any) any }

معنی هر کدام:

Context یک interface با ۴ تابع اصلی
Context یک interface با ۴ تابع اصلی


انواع Context ابتدایی

context.Background()

ریشهٔ درخت Context. معمولاً برای شروع اپلیکیشن.

context.TODO()

وقتی هنوز نمی‌دانیم چه Context لازم داریم.


ساخت Context قابل لغو

ctx, cancel := context.WithCancel(context.Background()) defer cancel()

لغو عملیات:

cancel()

Context با Timeout

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel()

بعد از 3 ثانیه، ctx.Done() بسته می‌شود.


Context با Deadline

deadline := time.Now().Add(2 * time.Second) ctx, cancel := context.WithDeadline(context.Background(), deadline) defer cancel()

ارسال مقدار در Context

طبق مستندات Go:

  • فقط اطلاعات سبک، غیر حساس و غیر ضروری باید در Context ذخیره شود.

  • برای داده‌های سنگین یا state از آن استفاده نکنید.

مثال:

ctx := context.WithValue(context.Background(), "requestID", "ABC-123")

مثال عملی: مدیریت Timeout در یک API

در این مثال یک API می‌سازیم که درخواست‌های سنگین را با Context مدیریت می‌کند.

هدف مثال

  • وقتی کار بیش از حد طول کشید → خودکار قطع شود

  • اگر کلاینت درخواست را لغو کرد → Goroutine‌ها هم لغو شوند

  • همراه با log و requestID


کد کامل مثال

package main import ( "context" "fmt" "log" "net/http" "time" ) func main() { http.HandleFunc("/process", handler) fmt.Println("Server running on :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } func handler(w http.ResponseWriter, r *http.Request) { // ساخت context با timeout ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second) defer cancel() // اضافه کردن requestID به context ctx = context.WithValue(ctx, "requestID", time.Now().UnixNano()) resultChan := make(chan string) // شروع یک عملیات سنگین go func() { // شبیه‌سازی کار ۵ ثانیه‌ای time.Sleep(5 * time.Second) resultChan <- "Operation Completed" }() select { case <-ctx.Done(): // Timeout یا لغو شدن log.Println("Canceled:", ctx.Value("requestID"), ctx.Err()) http.Error(w, "Request Timeout", http.StatusRequestTimeout) return case result := <-resultChan: // موفقیت‌آمیز fmt.Fprintln(w, result) } }

برای دسترسی به سورس‌کد کامل مثال Context در Golang، به ریپازیتوری اختصاصی این مقاله در GitHub مراجعه کنید:
https://github.com/h-agharezaei/go-context-02.git

تحلیل دقیق مثال

زمان پیش‌فرض عملیات ۵ ثانیه است ولی Context فقط ۳ ثانیه فرصت می‌دهد.

بنابراین:

  • عملیات به اتمام نمی‌رسد

  • ctx.Done() بعد از ۳ ثانیه بسته می‌شود

  • درخواست لغو می‌شود

  • Goroutine پاک‌سازی می‌شود

ویژگی مهم

اگر کلاینت (مثلاً Postman) درخواست را Cancel کند، سرویس Go به‌طور خودکار Context را Cancel می‌کند.


Best Practices استفاده از Context در Go

✔ همیشه Context را در اولین آرگومان تابع قرار دهید:

func fetchData(ctx context.Context) {}

✔در توابع سطح پایین (service، repo، helper)، نباید از Background ، TODO یا WithCancel برای ساختن context استفاده کنید. Context باید از caller بیاید.

✔ از Context برای انتقال اطلاعات مهم یا ساختارهای سنگین استفاده نکنید

✔ برای database، http، grpc حتماً از Context استفاده کنید

✔ Context باید توسط caller مدیریت شود، نه callee


جمع‌بندی

Context یکی از مهم‌ترین ابزارهای Go برای مدیریت:

  • زمان اجرای عملیات

  • لغو کارها

  • کنترل goroutineها

  • جلوگیری از memory leak

  • ارتباط بهتر بین لایه‌های نرم‌افزار

در این مقاله یاد گرفتید:

  • Context چیست و چرا استفاده می‌شود

  • انواع Context

  • Timeout، Deadline و Cancel

  • انتقال مقدار

  • یک مثال واقعی در سطح production

contextgoconcurrency
۰
۰
Roham
Roham
پیدا کردن خودم توی نوشته ها برام جذابه بهم یه حس خوب بودن می ده مخصوصا وقتی با طعم علم و خلاقیت همراه باشه هر روز که بیشتر با این دنیا آشنا می شم حس بهتری برای بیشتر دونستن و یاد دادن درونم رشد می کنه
شاید از این پست‌ها خوشتان بیاید