Sobes.tech
Middle

რა მიდგომა გამოიყენება გო-ში გორუტინებში წარმოქმნილი შეცდომების დამუშავებისთვის?

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)
        }
      }()
    
      // დასრულების ან სხვა ლოგიკის მოლოდინში
      // ...
    }
    

შერჩევა კონკრეტული მიდგომის დამოკიდებულია შეცდომების დამუშავების მოთხოვნებზე და პროგრამის არქიტექტურაზე.