Dalam model konkurensi Go, pilih ialah binaan berkuasa yang membolehkan gorout menunggu berbilang saluran secara serentak. Walau bagaimanapun, perangkap biasa timbul apabila cuba merantai operasi saluran dalam kes terpilih, kerana ia boleh membawa kepada tingkah laku yang tidak dijangka dan kemungkinan kebuntuan.
Pertimbangkan coretan kod berikut, yang cuba memultiplekskan dua saluran (A dan B ) dengan kelewatan masa yang berbeza menggunakan pilih:
func main() { ch := fanIn(talk("A", 10), talk("B", 1000)) for i := 0; i < 10; i++ { fmt.Printf("%q\n", <-ch) } }
Dalam contoh ini, ceramah mengembalikan saluran yang menghantar urutan mesej dengan kelewatan tertentu. fanIn ialah fungsi pembantu yang mencipta saluran baharu yang menerima nilai daripada kedua-dua input1 dan input2 menggunakan pernyataan pilih.
Apabila pernyataan kes pilih diubah suai kepada yang berikut:
select { case ch <- <-input1: case ch <- <-input2: }
an hasil yang tidak dijangka berlaku. Sesetengah nilai digugurkan, dan akhirnya, kebuntuan berlaku kerana tiada lagi nilai diterima oleh saluran kipas masuk.
Untuk memahami tingkah laku ini, adalah penting untuk memahami konsep operasi menyekat dan tidak menyekat dalam pilih. Dalam pernyataan pilihan, hanya satu saluran operasi baca atau tulis tidak disekat pada bila-bila masa. Semua operasi lain berkelakuan seperti biasa.
Dalam kes pilihan yang diubah suai, operasi menerima saluran (<-input1 dan <-input2) adalah tidak menyekat. Ini bermakna mereka kembali serta-merta, walaupun tiada nilai yang akan diterima.
Akibat daripada tingkah laku tidak menyekat ini ialah apabila operasi terima pertama berjaya (cth., daripada <-input1), ia berbunyi dan menyimpan nilai. Walau bagaimanapun, operasi ch <- berikutnya mungkin masih disekat walaupun ia tidak menyekat. Sekatan ini berlaku kerana gelung fungsi utama belum lagi menggunakan nilai daripada saluran gabungan.
Akibatnya, nilai digugurkan, membawa kepada kebuntuan yang diperhatikan.
Untuk tingkah laku yang betul, pastikan bahawa hanya operasi hantar atau terima akhir dalam kes terpilih tidak disekat. Dalam erti kata lain, gunakan pengendali tugasan := bukannya pengendali anak panah <- untuk operasi terima perantaraan.
select { case t := <-input1: ch <- t case t := <-input2: ch <- t }
Dengan melaraskan kes pilihan dengan cara ini, operasi saluran dirantai dengan betul dan semua nilai dihantar dan diterima dengan betul tanpa risiko kehilangan nilai atau kebuntuan.
Atas ialah kandungan terperinci Bagaimanakah Operasi Saluran Berantai dalam Pernyataan `select` Go Mempengaruhi Gelagat Penyekatan dan Bukan Penyekatan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!