Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closing the channel vs. sending e.g. an empty struct?

I have a pipeline with goroutines connected by channels so that each goroutine will trigger another one until all have run. Put even simpler, imagine two goroutines A and B so that when A is done it should tell B it can run.

It's working fine and I have tried a few variants as I have learnt more about pipelines in Go.

Currently I have a signalling channel

ch := make(chan struct{})
go A(ch)
go B(ch)
...

that B blocks on

func B(ch <-chan struct{}) {
    <-ch
    ...

and A closes when done

func A(ch chan struct{}) {
    defer close(ch)
    ...
}

This works fine and I also tried, instead of closing, sending an empty struct struct{} in A().

Is there any difference between closing the channel or sending the empty struct? Is either way cheaper / faster / better?

Naturally, sending any other type in the channel takes up "some" amount of memory, but how is it with the empty struct? Close is just part of the channel so not "sent" as such even if information is passed between goroutines.

I'm well aware of premature optimization. This is only to understand things, not to optimize anything.

Maybe there's an idiomatic Go way to do this even?

Thanks for any clarification on this!

like image 652
murrekatt Avatar asked Sep 02 '25 10:09

murrekatt


1 Answers

closing a channel indicates that there will be no more sends on that channel. It's usually preferable, since you would get a panic after that point in the case of an inadvertent send or close (programming error). A close also can signal multiple receivers that there are no more messages, which you can't as easily coordinate by just sending sentinel values.

Naturally, sending any other type in the channel takes up "some" amount of memory, but how is it with the empty struct?

There's no guarantee that it does take any extra memory in an unbuffered channel (it's completely an implementation detail). The send blocks until the receive can proceed.

Close is just part of the channel so not "sent" as such even if information is passed between goroutines.

There's no optimization here, close is simply another type of message that can be sent to a channel.

Each construct has a clear meaning, and you should use the appropriate one.

  • Send a sentinel value if you need to signal one receiver, and keep the channel open to send more values.

  • Close the channel if this is the final message, possibly signal multiple receivers, and it would be an error to send or close again.

like image 186
JimB Avatar answered Sep 05 '25 01:09

JimB