Context ในภาษา Go เป็นเครื่องมือที่ทรงพลังที่ช่วยให้เราจัดการกับการควบคุมเวลา, การยกเลิก (cancellation), และการส่งข้อมูลข้าม goroutine ได้อย่างมีประสิทธิภาพ บทความนี้จะช่วยให้คุณเข้าใจ context อย่างลึกซึ้ง พร้อมทั้งยกตัวอย่าง code และกรณีใช้งานจริง
Context คืออะไร?
ในภาษา Go แพคเกจ context
ถูกออกแบบมาเพื่อ:
- ส่งสัญญาณยกเลิกการทำงาน (cancellation signal)
- ควบคุม timeout ของการทำงาน
- ส่งค่าระหว่าง goroutine ได้แบบ thread-safe
ประเภทของ Context
context.Background()
: ใช้เมื่อเริ่มต้นcontext.WithCancel()
: สร้าง context ที่สามารถยกเลิกได้context.WithTimeout()
: สร้าง context ที่ยกเลิกอัตโนมัติเมื่อถึงเวลาcontext.WithDeadline()
: เหมือน timeout แต่กำหนดเวลาตายตัว
1. context.WithCancel ตัวอย่าง
func main() { ctx, cancel := context.WithCancel(context.Background()) go func(ctx context.Context) { for { select { case <-ctx.Done(): fmt.Println("Canceled") return default: fmt.Println("Working...") time.Sleep(500 * time.Millisecond) } } }(ctx) time.Sleep(2 * time.Second) cancel() time.Sleep(1 * time.Second) }
2. context.WithTimeout ตัวอย่าง
func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() select { case <-time.After(3 * time.Second): fmt.Println("Finished work") case <-ctx.Done(): fmt.Println("Timeout:", ctx.Err()) } }
3. ใช้ Context กับ HTTP Request
กรณีเรียก API แล้วต้องหยุดเมื่อเกิน 3 วินาที
func fetchAPI(ctx context.Context, url string) error { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return err } client := http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() // handle response return nil } func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := fetchAPI(ctx, "https://example.com") if err != nil { fmt.Println("Request failed:", err) } }
Best Practices ในการใช้ Context
- ไม่ควรเก็บ context ใน struct
- ส่ง context เป็น argument แรกในฟังก์ชัน
- เรียก
cancel()
เสมอหลังจากWithTimeout/WithCancel
- ใช้
context.TODO()
แทนnil
เมื่อยังไม่รู้ว่าจะใช้ context อะไร
ภาพแสดงการทำงานของ Context

Context Chain และการสืบทอด
Context ใน Go มีลักษณะเป็น parent-child chain หาก context ต้นทางถูก cancel ลูกทั้งหมดจะหยุดทันที
ctx := context.Background() ctx1, cancel1 := context.WithCancel(ctx) ctx2, cancel2 := context.WithTimeout(ctx1, 1*time.Second) ctx3 := context.WithValue(ctx2, "user", "admin") // เมื่อ cancel1() ถูกเรียก ctx2 และ ctx3 จะโดนยกเลิกด้วย cancel1()
เมื่อต้องใช้ vs ไม่ต้องใช้ Context
ควรใช้ Context เมื่อ:
- มี HTTP request ที่ควบคุมเวลา
- มี long-running task หรือ background task
- ต้องควบคุม pipeline หรือ queue งานแบบ async
ไม่ควรใช้ Context เพื่อ:
- ส่งข้อมูลทั่วไป (ควรใช้ struct)
- เก็บค่าที่ไม่เกี่ยวข้องกับเวลา
สรุป
การเข้าใจ Context เป็นสิ่งสำคัญสำหรับการพัฒนาแอปพลิเคชัน Go ที่ดี โดยเฉพาะระบบที่มี concurrency, HTTP API, หรือ background task หากใช้ context อย่างถูกต้อง ระบบจะสามารถควบคุมงานได้ยืดหยุ่น มีเสถียรภาพ และ resource ไม่รั่ว
คำค้น SEO: Go context, golang timeout, cancellation context Go, context best practice, context กับ HTTP request, context.Background กับ context.TODO ต่างกันยังไง