Rumah >pembangunan bahagian belakang >Golang >Menggunakan errgroup untuk melaksanakan kumpulan kerja Go, gorouti terperangkap
Editor PHP Apple hari ini memperkenalkan anda kepada kaedah menggunakan errgroup untuk melaksanakan kumpulan Go work, yang menyelesaikan masalah goroutine tersekat. Dalam pengaturcaraan serentak, pemprosesan serentak yang cekap boleh dicapai dengan menggunakan goroutine, tetapi apabila ralat atau tersekat berlaku dalam goroutine tertentu, ia akan menjejaskan pelaksanaan keseluruhan program. Dengan menggunakan pakej errgroup, kami boleh menguruskan perlaksanaan goroutine secara elegan dan mengendalikan ralat apabila ralat berlaku, memastikan kestabilan dan kebolehpercayaan program. Mari kita lihat bagaimana ini dilaksanakan.
Saya telah melaksanakan pola kumpulan pekerja menggunakan errgroup supaya ralat dalam mana-mana goroutine dapat ditangkap. Berikut adalah butiran saya:
jobs := make(chan usersinfo, totalusers) results := make(chan usersinfo, totalusers) g, gctx := errgroup.withcontext(ctx) for i := 1; i <= 4; i++ { g.go(func() error { err := workeruser(gctx, jobs, results) if err != nil { return err } return nil }) } for _, user := range usersresp { jobs <- user } close(jobs) var usersarray []usersinfo for i := 1; i <= totalusers; i++ { r := <-results usersarray = append(usersarray, r) } if err := g.wait(); err != nil { return nil, err }
Maka pelaksanaan fungsi pekerja adalah seperti berikut:
func workerUser(ctx context.Context, jobs <-chan UsersInfo, results chan<- UsersInfo) error { for { select { case <-ctx.Done(): return ctx.Err() case user, _ := <-jobs: userInfo, err := CallUserAPI(ctx, user) if err != nil { return err } results <- userInfo } } }
calluserapi mengembalikan ralat terlarang 403, yang sepatutnya memanggil g.wait() dan harus menghentikan semua goroutine serta-merta pada ralat bukan nol. Tetapi itu tidak berlaku di sini, g.wait() tidak pernah dipanggil.
Ada beberapa masalah:
Gelung
for i := 1; i <= totalusers; i++ { r := <-results usersarray = append(usersarray, r) }
Tunggu kakitangan menghantar keputusan untuk setiap pengguna. Ini tidak berlaku apabila calluserapi
mengembalikan ralat.
pekerja tidak mengendalikan jobs
situasi tertutup.
Kod berikut boleh menyelesaikan dua masalah ini:
Isytiharkan jenis, nyatakan pengguna mana yang hendak diproses dan tempat untuk meletakkan hasilnya:
type job struct { user usersinfo result *usersinfo }
Ubah suai urutan pekerja untuk menggunakan jenis baharu ini. Selain itu, ubah suai pekerja supaya ia keluar apabila jobs
ditutup.
func workeruser(ctx context.context, jobs <-chan job) error { for { select { case <-ctx.done(): return ctx.err() case job, ok := <-jobs: if !ok { // no more jobs, exit. return nil } var err error *job.result, err = calluserapi(ctx, job.user) if err != nil { return err } } } }
Lekatkan bersama dalam goroutine utama:
jobs := make(chan UsersInfo, totalUsers) usersArray := make([]UsersInfo, totalUsers) g, gCtx := errgroup.WithContext(ctx) // Start the workers. for i := 1; i <= 4; i++ { g.Go(func() error { return workerUser(gCtx, jobs) }) } // Feed the workers. for i, user := range usersResp { jobs <- job{user: user, result: &usersArray[i]} } // Close the channel to indicate that no more jobs will be sent. // The workers exit via the `if !ok { return nil }` statement. close(jobs) // Wait for the workers to complete. if err := g.Wait(); err != nil { return nil, err } // It is now safe to access the results in usersArray.
Atas ialah kandungan terperinci Menggunakan errgroup untuk melaksanakan kumpulan kerja Go, gorouti terperangkap. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!