Go: Menggunakan Tamat Masa dengan Saluran
Dalam Go, tamat masa dan saluran menyediakan cara yang mudah untuk mengawal pelaksanaan goroutin dan menyegerakkan keputusannya . Walau bagaimanapun, terdapat senario tertentu di mana kes tamat masa mungkin tidak dilaksanakan seperti yang dijangkakan.
Pernyataan Masalah
Pertimbangkan kod Go berikut:
import "fmt" import "time" func check(u string) bool { time.Sleep(4 * time.Second) return true } func IsReachable(urls []string) bool { ch := make(chan bool, 1) for _, url := range urls { go func(u string) { select { case ch <- check(u): case <-time.After(time.Second): ch <- false } }(url) } return <-ch } func main() { fmt.Println(IsReachable([]string{"url1"})) }
Matlamat kod ini adalah untuk menyemak sama ada semua URL dalam senarai yang disediakan boleh dicapai. Jika mana-mana URL gagal bertindak balas dalam masa sesaat, fungsi itu harus mengembalikan palsu.
Walau bagaimanapun, apabila melaksanakan kod ini, ia akan sentiasa kembali benar. Kes tamat masa tidak dapat dilaksanakan.
Penjelasan
Isu ini timbul kerana cara semak(u) dilaksanakan. Dalam fungsi IsReachable, setiap goroutine menyemak kebolehcapaian URL dengan memanggil check(u). Walau bagaimanapun, check(u) tidur selama 4 saat dalam goroutine semasa sebelum kembali.
Dalam penyataan pilih, kes ch <- check(u): branch ialah yang pertama tersedia, sebagai check( u) telah pun kembali. Ini menghalang kes tamat masa daripada pernah dilaksanakan, menyebabkan fungsi sentiasa kembali benar.
Penyelesaian
Untuk menyelesaikan isu ini, fungsi check(u) harus dilaksanakan dalam goroutine yang berasingan. Ini membolehkan penyataan pilih mengendalikan kes tamat masa dengan betul.
Berikut ialah kod yang dikemas kini:
import "fmt" import "time" func check(u string, checked chan<- bool) { time.Sleep(4 * time.Second) checked <- true } func IsReachable(urls []string) bool { ch := make(chan bool, 1) for _, url := range urls { go func(u string) { checked := make(chan bool) go check(u, checked) select { case ret := <-checked: ch <- ret case <-time.After(1 * time.Second): ch <- false } }(url) } return <-ch } func main() { fmt.Println(IsReachable([]string{"url1"})) }
Sekarang, jika mana-mana URL gagal bertindak balas dalam masa sesaat, fungsi akan kembali palsu. Selain itu, jika hanya satu URL tersedia, fungsi itu akan kembali benar.
Atas ialah kandungan terperinci Mengapa Tamat Masa Pergi Saya Tidak Berfungsi dalam Contoh Saluran ini?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!