Home > Backend Development > Golang > How Should Responsibility for Closing Channels in Go Generators Be Handled?

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

Mary-Kate Olsen
Release: 2024-12-08 11:56:17
Original
294 people have browsed it

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

Idiomatic Implementation of Generators with Yield

In Go, implementing generators using yield is typically achieved through a combination of goroutines and channels. The generator function creates a goroutine that yields values through a channel, and the consumer function receives those values from the channel in a for-range loop.

Responsibility for Closing the Channel

According to the Go idioms, the responsibility for closing the channel falls on the generator function. Since the generator has the knowledge of when the iteration is complete, it should close the channel to signal to the consumer that no more values will be received.

Modified Code with Caller Deferring Close()

In your modified code, you have correctly placed the responsibility for closing the channel on the caller by not closing it in the generator function. However, you should also remove the close() call in the main() function, as it is incorrect to close a channel that is already closed.

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
        }
    }
}
Copy after login

Negative Side-Effects of Closing a Closed Channel

When the caller closes the channel, any subsequent attempts to send values to it will result in a runtime panic. This is because the channel is marked as closed, and sending to a closed channel is illegal. However, this panic does not have any negative side effects beyond terminating the goroutine that attempted to send values.

Receive-Only Channel Return Type

To restrict the channel returned by the library function to receive-only, while still allowing the caller to close it, you can introduce a new type that wraps the channel and exposes only the receive-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)
}
Copy after login

By wrapping the channel in a new type, you can restrict its accessibility to only receive operations while still allowing the caller to close it through the Close() method of the wrapper type.

The above is the detailed content of How Should Responsibility for Closing Channels in Go Generators Be Handled?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template