Go'догу гурутиндерде пайда болгон каталардын иштетилиши үчүн кайсы ыкма колдонулат?
sobes.tech AI
AIден жооп
Go'до ката кетирүү үчүн көбүнчө төмөнкү ыкмалар колдонулат:
-
Ката өткөрүү аркылуу каналдар: Ката өткөрүү үчүн канал түзүлөт, ал негизги агымга же башка горутинага өткөрүлүп, алар аны иштетиши мүмкүн:
// Ката өткөрүү мисалы канал аркылуу func worker(id int, errors chan<- error) { // ... ишти аткаруу if somethingWentWrong { errors <- fmt.Errorf("горутинада каталар %d", id) return } // ... ийгиликтүү аяктоо } func main() { errorCh := make(chan error, nWorkers) // Багдарланган канал for i := 0; i < nWorkers; i++ { go worker(i, errorCh) } for i := 0; i < nWorkers; i++ { err := <-errorCh if err != nil { log.Printf("табылган каталар: %v", err) // Катаны иштетүү } } } -
sync.WaitGroupжана ката каналдарын колдонуу:sync.WaitGroupбардык горутинадардын аяктоосун күтүүгө жардам берет, ал эми канал каталардын топтолушу үчүн колдонулат:// WaitGroup жана ката каналдары менен мисал func workerWithWG(id int, wg *sync.WaitGroup, errors chan<- error) { defer wg.Done() // ... ишти аткаруу if somethingWentWrong { errors <- fmt.Errorf("горутинада каталар %d", id) } } func main() { var wg sync.WaitGroup errorCh := make(chan error, nWorkers) for i := 0; i < nWorkers; i++ { wg.Add(1) go workerWithWG(i, &wg, errorCh) } wg.Wait() close(errorCh) // WaitGroup аяктагандан кийин каналды жабуу маанилүү for err := range errorCh { log.Printf("табылган каталар: %v", err) // Катаны иштетүү } } -
Кайтарылган мааниси жана ката менен функцияны иштетүү: Эгер горутина конкреттүү ишти аткарып, натыйжаны жана/же катаны кайтара алса, аны функцияга ороп, ошол маанилерди кайтарууга болот:
// Мисал кайтарылган мааниси жана ката менен функция type result struct { value int err error } func doSomething(id int) (int, error) { // ... ишти аткаруу if somethingWentWrong { return 0, fmt.Errorf("горутинада каталар %d", id) } return id * 10, nil } func main() { results := make(chan result, nWorkers) for i := 0; i < nWorkers; i++ { go func(idx int) { val, err := doSomething(idx) results <- result{val, err} }(i) } for i := 0; i < nWorkers; i++ { res := <-results if res.err != nil { log.Printf("табылган каталар: %v", res.err) // Катаны иштетүү } else { log.Printf("жыйынтык: %d", res.value) } } } -
Контекстти (
context.Context) колдонуу менен алмашуу жана каталарды иштетүү: Контекст горутинадардын алмашуусун сигнализациялоо же катаны төмөнкү деңгээлге өткөрүү үчүн колдонулушу мүмкүн:// Контекст менен мисал func workerWithContext(ctx context.Context, id int, errors chan<- error) { select { case <-ctx.Done(): errors <- fmt.Errorf("горутина %d алмаштырылды: %v", id, ctx.Err()) return default: // ... ишти аткаруу if somethingWentWrong { errors <- fmt.Errorf("горутинада каталар %d", id) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) errorCh := make(chan error, nWorkers) for i := 0; i < nWorkers; i++ { go workerWithContext(ctx, i, errorCh) } // Бир аз убакыттан кийин cancel() чакырсаңыз болот // cancel() // Каталардын жыйнагы go func() { for err := range errorCh { log.Printf("табылган каталар: %v", err) } }() // Аякталышын күтүү же башка логика // ... }
Конкреттүү ыкма тандоо каталардын иштетүү талаптарына жана программалык архитектурага көз каранды.