Goда бир нече goroutine-дун ишин туура бүтүрүү жолдору?
sobes.tech AI
AIден жооп
Көптөгөн кеңири тараган ыкмалар бар:
-
Контекстти колдонуу (Context): Аралык структураларында операцияларды жокко чыгаруу үчүн сунушталган ыкма. Контекст канал аркылуу жокко чыгаруу сигналын өткөрө алат.
package main import ( "context" "fmt" "time" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Горутина %d аяктайт: %v\n", id, ctx.Err()) return default: fmt.Printf("Горутина %d иштеп жатат...\n", id) time.Sleep(1 * time.Second) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) go worker(ctx, 1) go worker(ctx, 2) time.Sleep(3 * time.Second) cancel() // Жокко чыгаруу сигналын жөнөтүү time.Sleep(1 * time.Second) // Горутинадардын аяктоо үчүн убакыт берүү fmt.Println("Негизги программа аяктады.") } -
Каналдар колдонуу: Специальдуу канал аркылуу (мисалы, бош структура
struct{}) сигнал жөнөтүү менен, горутинага аяктоо керектигин кабарлай аласыз.package main import ( "fmt" "time" ) func worker(stopChan <-chan struct{}, id int) { for { select { case <-stopChan: fmt.Printf("Горутина %d канал аркылуу аяктайт\n", id) return default: fmt.Printf("Горутина %d иштеп жатат...\n", id) time.Sleep(1 * time.Second) } } } func main() { stopChan := make(chan struct{}) go worker(stopChan, 1) go worker(stopChan, 2) time.Sleep(3 * time.Second) close(stopChan) // Каналды жабуу аяктоо белгиленет time.Sleep(1 * time.Second) // Горутинадардын аяктоо үчүн убакыт берүү fmt.Println("Негизги программа аяктады.") } -
sync.WaitGroupколдонуу (чакыруу үчүн, сигнал берүү үчүн эмес):WaitGroupгруппадагы горутиндардын аяктоосун күтүүгө колдонулат, бирок өзү токтотуу механизмин камсыз кылбайт. Аны көбүнчө контекст менен же каналдар менен бирге колдонушат.package main import ( "context" "fmt" "sync" "time" ) func worker(ctx context.Context, wg *sync.WaitGroup, id int) { defer wg.Done() // Горутина аяктагандан кийин `WaitGroup` санын азайтат for { select { case <-ctx.Done(): fmt.Printf("Горутина %d аяктайт\n", id) return default: fmt.Printf("Горутина %d иштеп жатат...\n", id) time.Sleep(1 * time.Second) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) var wg sync.WaitGroup numWorkers := 2 wg.Add(numWorkers) // `WaitGroup` баштоо for i := 1; i <= numWorkers; i++ { go worker(ctx, &wg, i) } time.Sleep(3 * time.Second) cancel() // Жокко чыгаруу сигналы wg.Wait() // Бардык горутиндардын аяктоосун күтүү fmt.Println("Негизги программа аяктады.") }
Тандоо конкреттүү колдонуу жагдайына жана горутиндардын өз ара аракеттешүүсүнүн татаалдыгына көз каранды. Контекст көбүнчө каскаддык жокко чыгаруу үчүн артыкчылык берилет.