ホームページ >バックエンド開発 >Golang >Go ジェネレーターでチャネルを閉じる責任はどのように扱われるべきですか?

Go ジェネレーターでチャネルを閉じる責任はどのように扱われるべきですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-08 11:56:17295ブラウズ

How Should Responsibility for Closing Channels in Go Generators Be Handled?

Yield を使用したジェネレーターの慣用的な実装

Go では、Yield を使用したジェネレーターの実装は、通常、ゴルーチンとチャネルの組み合わせによって実現されます。ジェネレーター関数はチャネルを通じて値を生成するゴルーチンを作成し、コンシューマー関数は for-range ループでチャネルからそれらの値を受け取ります。

チャネルを閉じる責任

によるとGo のイディオムでは、チャネルを閉じる責任はジェネレーター関数にあります。ジェネレータは反復がいつ完了するかを知っているため、チャネルを閉じて、これ以上値を受信しないことをコンシューマに通知する必要があります。

Caller Deferring Close() を使用した修正コード

修正したコードでは、ジェネレーター関数内でチャンネルを閉じずに、呼び出し元にチャンネルを閉じる責任を正しく設定しました。ただし、すでに閉じているチャネルを閉じるのは正しくないため、main() 関数の close() 呼び出しも削除する必要があります。

package main

import (
    "./lib"
    "fmt"
)

var (
    fruits  = []string{"apple", "banana", "cherry", "durian"}
    banned = "durian"
)

func main() {
    channel := lib.PermutateWithChannel(fruits)
    defer close(channel) // Defer closing the channel

    for myFruits := range channel {
        fmt.Println(myFruits)
        if myFruits[0] == banned {
            break // Break from the loop instead of closing the channel
        }
    }
}

閉じたチャネルを閉じることによるマイナスの副作用

呼び出し元がチャネルを閉じると、その後そのチャネルに値を送信しようとすると、実行時パニックが発生します。これは、チャネルが閉鎖済みとしてマークされており、閉鎖されたチャネルへの送信が違法であるためです。ただし、このパニックには、値を送信しようとしたゴルーチンが終了する以上の悪影響はありません。

受信専用チャネルの戻り値の型

ライブラリ関数によって返されるチャネルを受信に制限します。 -only では、呼び出し元がチャネルを閉じることを許可しながら、チャネルをラップして受信専用のみを公開する新しい型を導入できます。 channel:

type ReceiveOnlyChannel <-chan []string

func NewReceiveOnlyChannel(channel <-chan []string) *ReceiveOnlyChannel {
    return (*ReceiveOnlyChannel)(&channel)
}

func PermutateWithChannel(strings []string) *ReceiveOnlyChannel {
    // ... (same as before, except it returns ReceiveOnlyChannel)
}

チャネルを新しい型でラップすることで、呼び出し元がラッパー型の Close() メソッドを通じてチャネルを閉じることを許可しながら、そのアクセスを操作の受信のみに制限できます。

以上がGo ジェネレーターでチャネルを閉じる責任はどのように扱われるべきですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。