WithCancel และ WithTimeout
สร้างบริบทที่ยกเลิกได้และมีเวลาจำกัด
WithCancel และ WithTimeout เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
context.WithCancel
WithCancel สร้างบริบทใหม่พร้อมฟังก์ชันยกเลิก เมื่อเรียก cancel ช่องสัญญาณ Done ของบริบทที่สร้างขึ้นและบริบทลูกทั้งหมดจะถูกปิด
ctx, cancel := context.WithCancel(parent)
defer cancel() // always call to release resources
go doWork(ctx)ควร defer cancel เสมอ
หากไม่เรียก cancel จะทำให้โกโรทีนที่เฝ้าติดตามบริบทแม่รั่วไหล ควร defer cancel ทันทีหลังจากสร้างบริบทที่ยกเลิกได้
context.WithTimeout
WithTimeout สร้างบริบทที่ยกเลิกโดยอัตโนมัติหลังจากระยะเวลาที่กำหนด เป็นตัวห่อหุ้มเพื่อความสะดวกของ WithDeadline
ctx, cancel := context.WithTimeout(parent, 5*time.Second)
defer cancel()
if err := db.QueryContext(ctx, query); err != nil {
// err may be context.DeadlineExceeded
}การตรวจสอบ Err()
หลังจาก Done ถูกปิดแล้ว ctx.Err() จะส่งคืนสาเหตุ ได้แก่ context.Canceled (ถูกยกเลิกอย่างชัดเจน) หรือ context.DeadlineExceeded (หมดเวลา)
if err := ctx.Err(); errors.Is(err, context.DeadlineExceeded) {
log.Println("timeout")
}การยกเลิกจากโกโรทีนอื่น
ฟังก์ชันยกเลิกปลอดภัยเมื่อเรียกจากโกโรทีนใดก็ได้ และเมื่อเรียกพร้อมกันจากหลายโกโรทีน มีเพียงการเรียกครั้งแรกเท่านั้นที่มีผล
ctx, cancel := context.WithCancel(context.Background())
go func() {
if detectError() { cancel() }
}()การหมดเวลาของคำขอ HTTP
ตั้งค่าการหมดเวลาต่อคำขอได้ด้วย WithTimeout บนบริบทของคำขอขาเข้า:
func handler(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
result, err := service.Call(ctx)
// ...
}การยกเลิกแบบต่อเนื่อง
หากบริบทแม่ถูกยกเลิก บริบทที่สร้างต่อมาทั้งหมด ได้แก่ บริบทลูกและหลาน จะถูกยกเลิกโดยอัตโนมัติ ทำให้โกโรทีนทั้งหมดในต้นไม้การเรียกหยุดทำงาน
Context ในการทดสอบ
ใช้ context.Background() หรือ context.WithTimeout ในการทดสอบ เพื่อจำกัดระยะเวลาของโกโรทีนที่เริ่มโดยการทดสอบ
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
testResult := runTest(ctx)การส่งต่อบริบทผ่านไลบรารี
ส่งบริบทที่ได้รับมาให้การเรียกขาออกเสมอ เช่น คำค้นฐานข้อมูล การเรียก HTTP และ RPC ห้ามละทิ้งหรือแทนที่บริบทนั้น เว้นแต่จะมีเหตุผลเฉพาะในการตั้งกำหนดเวลาสิ้นสุดใหม่
การสร้างบริบทสำหรับงานเบื้องหลัง
สำหรับงานเบื้องหลังที่ไม่ผูกกับคำขอ ให้ใช้ context.Background() เป็นราก แล้วเพิ่ม WithCancel เพื่อให้งานหยุดทำงานได้อย่างเรียบร้อย
การใช้ select กับ Done
ควรใช้ select ตรวจสอบ ctx.Done() ควบคู่กับช่องสัญญาณงานเสมอ เพื่อป้องกันการบล็อกเมื่อบริบทถูกยกเลิกก่อนงานจะเสร็จสิ้น
select {
case result := <-workCh:
return result, nil
case <-ctx.Done():
return nil, ctx.Err()
}ตรวจสอบอย่างรวดเร็ว
context.WithCancel และ context.WithTimeout แตกต่างกันอย่างไร
สรุป: WithCancel และ WithTimeout
ประเด็นสำคัญ:
- ควร defer cancel() ทันทีหลังจากสร้างบริบทเสมอ
- WithTimeout ยกเลิกโดยอัตโนมัติหลังจากระยะเวลาที่กำหนด และส่งคืน DeadlineExceeded
- ctx.Err() แยกความแตกต่างระหว่าง Canceled กับ DeadlineExceeded
- การยกเลิกส่งต่อไปยังบริบทที่สร้างต่อมาทั้งหมด
คำถามที่พบบ่อย
บทเรียน “WithCancel และ WithTimeout” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “WithCancel และ WithTimeout” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “WithCancel และ WithTimeout”
สร้างบริบทที่ยกเลิกได้และมีเวลาจำกัด คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “WithCancel และ WithTimeout” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม
ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุผลที่มี context.Context
- WithCancel และ WithTimeout
- WithDeadline และ WithValue
- Context ในการเรียกใช้ HTTP และฐานข้อมูล