Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Melaksanakan Penjana Go Secara Idiomatik Menggunakan Goroutine dan Saluran?
Cara Idiomatik untuk Melaksanakan Penjana dengan Yield in Go untuk Fungsi Rekursif
Dalam Go, melaksanakan penjana menggunakan kata kunci hasil tidak disokong secara langsung oleh bahasa. Walau bagaimanapun, pendekatan idiomatik adalah untuk mensimulasikan fungsi ini menggunakan goroutine dan saluran. Berikut ialah pemeriksaan lebih dekat bagi soalan anda:
1. Cara Idiomatik untuk Melaksanakan Penjana
Cara paling idiomatik untuk melaksanakan penjana dengan gelagat yang sama seperti hasil ialah mempunyai fungsi berasaskan goroutine yang menghantar nilai ke dalam saluran. Goroutine ini harus menutup saluran apabila semua nilai telah dijana. Berikut ialah contoh:
package main import ( "fmt" "time" ) // Generate integers in a goroutine. func generateIntegers(numbers []int, c chan<- int) { defer close(c) for _, n := range numbers { c <- n time.Sleep(time.Second) // Simulate delay for clarity } } func main() { numbers := []int{1, 2, 3, 4, 5} c := make(chan int) go generateIntegers(numbers, c) // Consume the generated values. for v := range c { fmt.Println(v) } }
2. Tanggungjawab Menutup Saluran
Secara idiomatik, fungsi penjana (yang menghasilkan nilai) harus bertanggungjawab untuk menutup saluran. Ini memastikan saluran ditutup apabila semua nilai telah dijana, membolehkan pengguna mengetahui masa untuk berhenti menerima nilai.
3. Pengubahsuaian Kod
Pengubahsuaian yang dicadangkan anda, untuk menjadikan pemanggil bertanggungjawab menutup saluran tanpa mengira sama ada ia memerlukan semua pilih atur atau tidak, juga merupakan pendekatan idiomatik. Walau bagaimanapun, adalah penting untuk menggunakan tangguh untuk memastikan saluran ditutup walaupun ralat berlaku.
// Modify the caller code: package main import ( "./lib" "fmt" ) var ( fruits = []string{"apple", "banana", "cherry", "durian"} banned = "durian" ) func main() { channel := lib.PermutateWithChannel(fruits) defer close(channel) for myFruits := range channel { fmt.Println(myFruits) if myFruits[0] == banned { // Close the channel when the banned fruit is encountered. // Since we're using defer, this will happen even if an error occurs. break } } }
4. Potensi Kesan Sampingan Negatif Menutup Saluran Selepas Pemanggil Menutupnya
Dalam contoh anda, pemanggil menutup saluran selepas penjana menghantar semua pilih atur. Walau bagaimanapun, goroutine yang menjalankan kod penjana mungkin masih cuba menghantar ke saluran tertutup. Ini tidak menyebabkan sebarang kesan sampingan negatif yang boleh diperhatikan, kerana goroutine hanya akan panik. Walau bagaimanapun, ia sentiasa disyorkan untuk menutup saluran hanya apabila ia tidak lagi diperlukan untuk mengelakkan tingkah laku yang tidak dijangka dan memastikan pengurusan sumber yang cekap.
5. Mengembalikan Saluran Terima Sahaja
Adalah mungkin untuk mengembalikan saluran terima sahaja daripada fungsi penjana. Ini menghalang pemanggil daripada menutup saluran, memastikan hanya penjana yang bertanggungjawab. Begini cara anda melakukannya:
// Generator function returns a receive-only channel. func generateIntegers(numbers []int) <-chan int { c := make(chan int) go func() { defer close(c) for _, n := range numbers { c <- n time.Sleep(time.Second) // Simulate delay for clarity } }() return c }
Ini memastikan pemanggil tidak dapat menutup saluran, menghalang isu yang diterangkan dalam soalan 4.
Atas ialah kandungan terperinci Bagaimana untuk Melaksanakan Penjana Go Secara Idiomatik Menggunakan Goroutine dan Saluran?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!