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

sync.WaitGroup

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

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

วัตถุประสงค์

sync.WaitGroup ใช้รอให้กลุ่มโกโรทีนทำงานเสร็จสิ้น โกโรทีนหลักจะเรียก Add เพื่อตั้งค่าจำนวน โกโรทีนแต่ละตัวจะเรียก Done เมื่อทำงานเสร็จ และ Wait จะบล็อกจนกว่าจำนวนจะลดลงเหลือศูนย์

การใช้งานพื้นฐาน

เรียก Add ก่อนเริ่มโกโรทีนแต่ละตัว เรียก Done เมื่อสิ้นสุดโกโรทีนแต่ละตัว (ผ่าน defer) และเรียก Wait หลังจากเริ่มโกโรทีนครบทั้งหมดแล้ว

var wg sync.WaitGroup
for _, item := range items {
    wg.Add(1)
    go func(v Item) {
        defer wg.Done()
        process(v)
    }(item)
}
wg.Wait()

ต้องเรียก Add ก่อนเริ่มโกโรทีน

เรียก wg.Add(1) ก่อน go func() และห้ามเรียกภายในโกโรทีน มิฉะนั้น Wait อาจส่งคืนก่อนที่โกโรทีนจะลงทะเบียนตัวเอง

ข้อผิดพลาดที่พบบ่อย: การจับตัวแปรของลูป

ส่งตัวแปรของลูปเป็นอาร์กิวเมนต์ให้ฟังก์ชันโกโรทีน ไม่ใช่ส่งผ่านคลอเชอร์ เพื่อป้องกันไม่ให้โกโรทีนทั้งหมดใช้ตัวแปรเดียวกันร่วมกัน

for _, v := range items {
    wg.Add(1)
    go func(item Item) { // correct: copy
        defer wg.Done()
        process(item)
    }(v)
}

การนำ WaitGroup กลับมาใช้ใหม่

คุณสามารถนำ WaitGroup กลับมาใช้ใหม่ได้หลังจาก Wait ส่งคืนแล้ว แต่ต้องแน่ใจว่าการเรียก Done ก่อนหน้าทั้งหมดส่งคืนแล้ว ห้ามนำกลับมาใช้พร้อมกันในขณะที่ยังมีการเรียก Done ค้างอยู่

WaitGroup พร้อมผลลัพธ์

WaitGroup ไม่รวบรวมผลลัพธ์ คุณต้องใช้ร่วมกับช่องสัญญาณหรือสไลซ์ (พร้อม mutex) เพื่อรวบรวมผลลัพธ์จากโกโรทีน

results := make([]Result, len(items))
for i, item := range items {
    wg.Add(1)
    go func(idx int, v Item) {
        defer wg.Done()
        results[idx] = process(v)
    }(i, item)
}
wg.Wait()

เรียก Add ด้วยจำนวนเป็นชุด

คุณสามารถส่งจำนวนทั้งหมดให้การเรียก Add เพียงครั้งเดียวก่อนลูปได้ ซึ่งมีประสิทธิภาพมากกว่าการเรียก Add หนึ่งครั้งต่อโกโรทีนเล็กน้อย

wg.Add(len(items))
for _, item := range items {
    go func(v Item) { defer wg.Done(); process(v) }(item)
}

ห้ามคัดลอก WaitGroup

เช่นเดียวกับ Mutex ห้ามคัดลอก WaitGroup หลังจากใช้งานครั้งแรก ควรส่งผ่านพอยน์เตอร์ หรือฝังไว้ในโครงสร้างที่ส่งผ่านพอยน์เตอร์

WaitGroup เทียบกับ errgroup

golang.org/x/sync/errgroup ห่อหุ้ม WaitGroup และเพิ่มการส่งต่อข้อผิดพลาด ควรใช้ errgroup เมื่อความล้มเหลวของโกโรทีนใดก็ตามควรทำให้โกโรทีนอื่นหยุดทำงาน

การใช้ร่วมกับบริบท

ใช้ errgroup.WithContext เพื่อให้ได้ทั้งพฤติกรรมของ WaitGroup และบริบทที่ถูกยกเลิกเมื่อเกิดข้อผิดพลาดแรก ทำให้โกโรทีนทั้งหมดหยุดทำงานอย่างเรียบร้อย

g, ctx := errgroup.WithContext(context.Background())
g.Go(func() error { return doWork(ctx) })
if err := g.Wait(); err != nil { log.Fatal(err) }

ค่า zero ใช้งานได้

ค่า zero ของ sync.WaitGroup พร้อมใช้งานได้ทันที ไม่จำเป็นต้องมีตัวสร้าง เพียงประกาศตัวแปรแล้วเรียก Add

ตรวจสอบอย่างรวดเร็ว

จะเกิดอะไรขึ้นหากคุณเรียก wg.Add(1) ภายในโกโรทีนแทนที่จะเรียกก่อนเริ่มโกโรทีน

สรุป: sync.WaitGroup

ประเด็นสำคัญ:

  • เรียก Add ก่อนเริ่มโกโรทีน และเรียก Done ผ่าน defer ภายในโกโรทีน
  • Wait จะบล็อกจนกว่าจำนวนจะลดลงเหลือศูนย์
  • ห้ามคัดลอก และห้ามเรียก Add ภายในโกโรทีน
  • ใช้ errgroup เพื่อส่งต่อข้อผิดพลาด

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

บทเรียน “sync.WaitGroup” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “sync.WaitGroup”

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

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

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

บทเรียน “sync.WaitGroup” ใช้เวลานานแค่ไหน

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

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

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

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

  1. sync.Mutex และ sync.RWMutex
  2. sync.WaitGroup
  3. sync.Once และ sync.Map
  4. ตัวตรวจจับภาวะแข่งขันและรูปแบบที่ปลอดภัย
← กลับไปที่ Go Academy