-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Channel size is one or none" forbids common and useful patterns #128
Comments
We often use channels with size 1 for notifications that something has changed, while the actual change is stored separately. The channel itself usually doesn't store anything meaningful (often just Background goroutine: for {
select {
case <-notifyCh:
// process state stored separately
case <-time.After(..):
// some periodic operations
case <-ctx.Done():
// exit
} Operation to trigger background goroutine: // mutate state for background goroutine
// notify the background goroutine
select {
case notifyCh <- struct{}{}:
default:
} So I don't think we should change the recommendation to unbuffered channels only. However, there are some use-cases where a specifically sized channel makes sense (typically sized as some concurrency limit), so we'll need to figure out how to cover those. |
To add to that, part of the intent behind the recommendation is to advice results := make(chan result, 1000) // should be enough
for _, item := range items {
go func(item *Item) {
results <- process(item)
}(item)
} With an unbuffered channel, or a channel with a deliberately chosen buffer |
Well, that's a leak 😬 Presumably you want a
Sure, that's a pattern, too — I just see it as roughly the same as the others I mentioned, both in utility and in frequency. I'm surprised to hear it's common for you; Go itself is async where it matters, so it's usually a mistake to "async all the things" in your application code, too. It's like re-implementing TCP on TCP, right? 😅 Backpressure is good!
Oh, yes, definitely. Cargo-culting "async is better" or whatever seems to worm its way into everything. Anyway, your call of course 👍 |
This was just a compressed example to indicate that it's waiting on other things. That said,
You may be thinking of
This pattern works quite well when work can be coalesced. |
Yes, but, that definitely counts :) If your time.After is 1s, and you get 100k sends on your notify channel in 1s, then you've got 100k time.Timers sitting around occupying memory. Hopefully you got a linter that catches this bug.
Yep, that one's even worse! |
Although I definitely appreciate and agree with the intent here, the rule as expressed forbids common patterns, such as the semaphore:
And scatter/gather:
Perhaps "Channels should be unbuffered by default"? There's nothing particularly special about a capacity of 1, I don't think, and all of the provided rationale still applies.
The text was updated successfully, but these errors were encountered: