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 ต่างกันยังไง