Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Melaksanakan Penjana Go Secara Idiomatik Menggunakan Goroutine dan Saluran?

Bagaimana untuk Melaksanakan Penjana Go Secara Idiomatik Menggunakan Goroutine dan Saluran?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-12-04 04:42:11611semak imbas

How to Idiomatically Implement Go Generators Using Goroutines and Channels?

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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn