Go Academy · บทเรียน

การปิดระบบอย่างราบรื่น

หยุดผู้ปฏิบัติงานอย่างเรียบร้อย

บทเรียน 4 จาก 413 ขั้นตอน

การปิดระบบอย่างราบรื่น เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุผลที่ต้องปิดระบบอย่างราบรื่น

ต้องแจ้งกอรูทีนที่ทำงานต่อเนื่องให้ทราบเมื่อถึงเวลาหยุด การปิดระบบอย่างราบรื่น ช่วยให้เวิร์กเกอร์ทำงานปัจจุบันให้เสร็จ ปล่อยทรัพยากร และออกจากการทำงานโดยไม่รั่วไหลหรือทำข้อมูลสูญหาย

  • ไม่มีกอรูทีนรั่วไหล
  • ไม่มีการเขียนข้อมูลที่ค้างอยู่ครึ่งหนึ่ง
  • กระบวนการออกจากการทำงานอย่างเรียบร้อย

รูปแบบแชนเนล done

แนวทางคลาสสิกคือแชนเนล done การปิดแชนเนลนี้จะกระจายสัญญาณหยุดไปยังกอรูทีนทั้งหมดที่รอฟังอยู่ เพราะการรับค่าจากแชนเนลที่ปิดแล้วจะส่งคืนทันที

done := make(chan struct{})
// ... later
close(done)

select สำหรับสัญญาณหยุด

เวิร์กเกอร์ใช้ select เพื่อเลือกว่าจะประมวลผลงานหรือรับรู้แชนเนล done เมื่อ done ถูกปิด กรณีดังกล่าวจะทำงานและเวิร์กเกอร์จะส่งคืนค่า

for {
    select {
    case <-done:
        return
    case j := <-jobs:
        process(j)
    }
}

context.Context

เครื่องมือสมัยใหม่ตามแนวทางของภาษา Go คือ context โดย context.WithCancel จะให้บริบทและฟังก์ชันยกเลิก การเรียกฟังก์ชันยกเลิกจะปิดแชนเนล Done ของบริบท

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

การรับฟังจาก ctx.Done()

เวิร์กเกอร์จะรอรับจาก ctx.Done() เมื่อมีการเรียกยกเลิกหรือพ้นกำหนดเวลา แชนเนลจะถูกปิดและเวิร์กเกอร์จะออกจากการทำงาน

select {
case <-ctx.Done():
    return ctx.Err()
case j := <-jobs:
    process(j)
}

การรอเวิร์กเกอร์

การส่งสัญญาณหยุดเพียงอย่างเดียวยังไม่พอ คุณต้องรอให้เวิร์กเกอร์ทำงานเสร็จจริง ๆ ด้วย sync.WaitGroup จะติดตามเวิร์กเกอร์เหล่านั้น เพื่อให้ main หยุดรอจนกว่าจำนวนจะเหลือศูนย์

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    runWorker(ctx)
}()
// ... later
cancel()
wg.Wait()

กำหนดเวลาหมดอายุด้วย context

context.WithTimeout จะยกเลิกโดยอัตโนมัติหลังผ่านระยะเวลาที่กำหนด วิธีนี้จำกัดระยะเวลาที่การปิดระบบจะใช้ได้ ก่อนที่คุณจะบังคับออกจากการทำงาน

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

การปิดระบบอย่างราบรื่นโดยสมบูรณ์

โปรแกรมนี้เรียกใช้เวิร์กเกอร์สองตัว ยกเลิกบริบท และรอให้ทั้งคู่ออกจากการทำงานอย่างเรียบร้อยก่อนพิมพ์ข้อความเสร็จสิ้น

package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

func worker(ctx context.Context, id int, wg *sync.WaitGroup) {
    defer wg.Done()
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("worker %d stopping\n", id)
            return
        case <-time.After(50 * time.Millisecond):
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    var wg sync.WaitGroup
    for i := 1; i <= 2; i++ {
        wg.Add(1)
        go worker(ctx, i, &wg)
    }
    time.Sleep(120 * time.Millisecond)
    cancel()
    wg.Wait()
    fmt.Println("all workers stopped")
}

การจัดการงานที่กำลังดำเนินอยู่ให้เสร็จ

ขณะปิดระบบ คุณมักต้องการให้เวิร์กเกอร์ทำงานที่เริ่มไว้แล้วให้เสร็จ อ่านงานที่เหลือในวงรอบสุดท้าย หรือหยุดรับงานใหม่พร้อมปล่อยให้งานปัจจุบันเสร็จสิ้น

การรับสัญญาณจากระบบปฏิบัติการ

ในเซิร์ฟเวอร์จริง signal.NotifyContext จะเชื่อมการยกเลิกเข้ากับ SIGINT และ SIGTERM เมื่อกด Ctrl+C ระบบจะใช้เส้นทางการปิดระบบอย่างราบรื่นแบบเดียวกับการยกเลิกด้วยตนเอง

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()

อย่าลืม cancel()

ใช้ defer cancel() เสมอ แม้จะใช้ WithTimeout ก็ตาม หากไม่เรียก cancel กอรูทีนภายในของบริบทและตัวจับเวลาจะรั่วไหลจนกว่ากำหนดเวลาจะหมด

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับการปิดระบบ

สรุปทบทวน

คุณได้เรียนรู้การปิดระบบอย่างราบรื่นดังนี้:

  • ใช้ context.WithCancel หรือแชนเนล done เพื่อส่งสัญญาณหยุด
  • เวิร์กเกอร์รอรับจาก ctx.Done()
  • WaitGroup รับประกันว่าเวิร์กเกอร์ทั้งหมดจะออกจากการทำงานจริง
  • เชื่อมการยกเลิกเข้ากับสัญญาณจากระบบปฏิบัติการสำหรับเซิร์ฟเวอร์จริง
  • ใช้ defer cancel() เสมอ
เริ่มต้นได้ฟรี

เรียนรู้ Go ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
51
บทเรียน
203

คำถามที่พบบ่อย

บทเรียน “การปิดระบบอย่างราบรื่น” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การปิดระบบอย่างราบรื่น” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การปิดระบบอย่างราบรื่น”

หยุดผู้ปฏิบัติงานอย่างเรียบร้อย คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การปิดระบบอย่างราบรื่น” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม

ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. รูปแบบกลุ่มผู้ปฏิบัติงาน
  2. Fan-Out Fan-In
  3. ขั้นตอนของกระบวนการประมวลผล
  4. การปิดระบบอย่างราบรื่น
← กลับไปที่ Go Academy