0Pricing
Go Academy · บทเรียน

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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เหตุผลที่มี context.Context
  2. WithCancel และ WithTimeout
  3. WithDeadline และ WithValue
  4. Context ในการเรียกใช้ HTTP และฐานข้อมูล
← กลับไปที่ Go Academy