首頁 > 後端開發 > Golang > 如何使用通道在 Go 中慣用地實現遞歸生成器?

如何使用通道在 Go 中慣用地實現遞歸生成器?

Susan Sarandon
發布: 2024-12-05 09:09:13
原創
860 人瀏覽過

How to Idiomatically Implement Recursive Generators in Go Using Channels?

在 Go 中慣用地實現遞歸函數的生成器

提供的程式碼示範了使用通道模擬 Python 風格的遞歸產生器函數。

慣用的實現

按照慣例,Go 中的生成器可以使用以下方式實現goroutine 和通道如下:

  • 使用匿名函數將產生器作為goroutine 啟動: 這允許正確處理關閉通道並響應來自消費者的訊號。
  • 讓生成器延遲關閉通道:這可以確保通道始終關閉,即使生成器恐慌。
  • 考慮使用訊號通道:這允許消費者與生成器進行通信,例如要求墮胎。

關閉通道的責任

通常,產生器函數應該負責關閉通道。這可以確保當生成器完成發送所有值時關閉通道。

修改後的程式碼

修改後的程式碼可以慣用地寫成如下:

func permutateWithChannel(channel chan<- []string, strings, prefix []string) {
    defer close(channel)
    length := len(strings)
    if length == 0 {
        channel <- prefix
        return
    }
    newStrings := make([]string, 0, length-1)
    for i, s := range strings {
        newStringsI := append(newStrings, strings[:i]...)
        newStringsI = append(newStringsI, strings[i+1:]...)
        newPrefixI := append(prefix, s)
        go permutateWithChannel(channel, newStringsI, newPrefixI)
    }
}

func PermutateWithChannel(strings []string) chan []string {
    channel := make(chan []string)
    prefix := make([]string, 0, len(strings))
    go permutateWithChannel(channel, strings, prefix)
    return channel
}
登入後複製

呼叫者

func main() {
    channel := lib.PermutateWithChannel(fruits)
    for myFruits := range channel {
        fmt.Println(myFruits)
        if myFruits[0] == banned {
            return
        }
    }
}
登入後複製

Goroutine終止與恐慌

消費者關閉通道後關閉通道不會引起恐慌。事實上,嘗試向關閉的通道發送值將導致關閉通道錯誤。

僅接收通道

將函式庫函數限制為僅接收,慣用的方法是使用單獨的通道類型來接收值和發送訊號。在這種情況下,函式庫函數將具有以下簽章:

func PermutateWithChannel(strings []string) (<-chan []string, chan<- struct{})
登入後複製

以上是如何使用通道在 Go 中慣用地實現遞歸生成器?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板