Kawalan Keutamaan dalam Pernyataan Pilih Go
Dalam Go, pernyataan pilih membenarkan komunikasi tak segerak antara goroutine. Walau bagaimanapun, susunan penilaian blok kes kadangkala boleh membawa kepada keputusan yang tidak dijangka. Isu ini timbul apabila cuba mengutamakan pengendalian kes tertentu, seperti segera keluar daripada rutin apabila konteks dibatalkan.
Pertimbangkan kod berikut:
func sendRegularHeartbeats(ctx context.Context) { for { select { case <-ctx.Done(): return case <-time.After(1 * time.Second): sendHeartbeat() } } }
The Masalah:
Dalam kod ini, tujuannya adalah untuk mengutamakan pengendalian kes ctx.Done() berbanding masa.Selepas() kes. Walau bagaimanapun, disebabkan oleh perintah penilaian bukan penentuan Go, kes masa.After() kadangkala dinilai dahulu, yang membawa kepada penghantaran degupan jantung walaupun konteksnya dibatalkan.
Penyelesaian:
Penyelesaian yang dicadangkan dalam jawapan yang diterima mencadangkan menambah pernyataan pilihan bersarang dengan semakan tidak menyekat untuk ctx.Done(). Walau bagaimanapun, ini tidak menangani isu ini sepenuhnya, kerana kebarangkalian degupan jantung dihantar kekal tinggi.
Pendekatan yang lebih berkesan ialah mengutamakan pengendalian kes ctx.Done() dengan menambahkan kes lalai pada pernyataan pilihan luar:
func sendRegularHeartbeats(ctx context.Context) { ticker := time.NewTicker(time.Second) defer ticker.Stop() for { select { case <-ctx.Done(): return default: } select { case <-ctx.Done(): return case <-ticker.C: sendHeartbeat() } } }
Ini memastikan kes ctx.Done() dinilai terlebih dahulu dalam pernyataan pilih luar, memberikannya lebih tinggi keutamaan. Jika konteks dibatalkan, rutin akan segera kembali dan tiada degupan jantung akan dihantar. Jika kes masa.After() tiba dahulu, ia akan diabaikan kerana kes lalai dalam penyataan pilih luar.
Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Mengutamakan Pembatalan Konteks dalam Penyata `pilih` Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!