Check Channel is active or not while Writing as writer Go routine

411 views
Skip to first unread message

Aniket Pandey

unread,
Oct 24, 2024, 9:08:33 AMOct 24
to golang-nuts
Has anyone have implemented the logic in order to check if the channel is active if the channel is active then only will write the data .if yes how to do so?  As i am getting the Following error: panic: send on closed channel

As a writer go routine i want to only write data to active channels
..

Jason E. Aten

unread,
Oct 24, 2024, 11:58:16 AMOct 24
to golang-nuts
Usually you just set to nil any channel you do not want to use. You do also have to
typically keep track of whether a channel is closed already or not in a separate
bool variable that is protected by a mutex. But anyway, a nil chan can
still be used in a select. But if nil, then select {} will ignore it.

Remember that channels are reference types (pointers inside; like maps) so setting your local 
copy of a chan to nil will not effect the copy of the same chan elsewhere.

You can even call a function within the select case that returns nil or live channel depending
on an arbitrary condition you decide on. I call this "conditional send" or "conditional receive".
It is a useful pattern.

also useful:
import "github.com/glycerine/idem"  // just FYI, see NewHalter() for handling shutdown and channel wrappers that can can have Close() called many times. Useful for cleanup/shutdown sequences that have inherent non-determinism/multipath races.

example of conditional send/receive:

regularChan := make(chan int)

select {
  case: myInt  := <- conditionalReceive(regularChan):
  ...
  case conditionalSend(regularChan) <- 9:
  ...
}

func conditionalReceive(regularChan chan int) chan int {
     if youWantToReceiveNow {
           return regularChan
     }
    return nil
func conditionalSend(regularChan chan int) chan int {
    if youWantToSendNow {
          return regularChan
     }
     return nil
}


robert engels

unread,
Oct 24, 2024, 12:42:35 PMOct 24
to Jason E. Aten, golang-nuts
In my experience, the OP’s issue points to a code structure problem and not having a deterministic lifecycle for the channels. 

You rarely need specific/additional state to track this. You can look at github.com/robaho/go-trader which uses multiple channels - it doesn’t even close them (it relies on controlling the reader/writer lifecycle based on other higher level state - once those are gone, the channels are collected).

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/db2345ea-b8e6-4a98-8280-a883cb09cdfen%40googlegroups.com.

Jason E. Aten

unread,
Oct 24, 2024, 1:07:27 PMOct 24
to golang-nuts
Robert makes an insightful point. You probably don't want to be closing channels that have actual data conveyed / sent through them in the first place.

Closing a channel is most often used as a means of broadcasting a state change, rather than signaling EOF (end of file). 

Doing for-range loop over a channel is a cute teaching example, but it should be banned because it misleads beginners.
They end up thinking they can write for-range over channels in production code, which is almost always a mistake,
because it prevents a clean shutdown being acheived; that where all goroutines have stopped.

So a practical design heuristic might be, only close channels that are chan struct{}, in other words, that are never going to convey data, and only going to broadcast a state change (typically that a task or job has completed, and one or more other goroutines want to know about that).

There are some good resources for reading about these patterns. The best I've seen are
these old talks from 10+ years ago. And read the Go language spec about channels and select. It is readable, unlike most specs.

Aniket Pandey

unread,
Oct 25, 2024, 8:57:58 AMOct 25
to golang-nuts
Thanks for the ideas guys !!
but in my case i have constant running process irrespective  number of writes as my writer channel won't stop sending data directly as it has only check  if the client Active and that is made false once the Socket Reader function exits and after that i close the channel where in somehow the Active(bool) tag is not in sync with other go routines which is a reference variable.
..

Jason E. Aten

unread,
Oct 25, 2024, 9:16:22 AMOct 25
to golang-nuts
Hi Aniket - you probably have a race and per Robert, should restructure not to close
the channel ever.  We can help you more directly if you would kindly post a playground 
code example that illustrates the essentials of what you are doing. 

See  https://go.dev/play/   then press Share and reply here with the link to your example.


Robert Engels

unread,
Oct 25, 2024, 10:23:19 AMOct 25
to Aniket Pandey, golang-nuts
That is exactly how the code I referenced you to works. Your structures appear inverted. When the client socket disconnects it should be removed from the structure the writer is using. If you don’t do this properly you have a race condition anyway. 

On Oct 25, 2024, at 7:57 AM, 'Aniket Pandey' via golang-nuts <golan...@googlegroups.com> wrote:

Thanks for the ideas guys !!

Nico Braun

unread,
Oct 27, 2024, 12:59:07 PMOct 27
to golang-nuts
On Thursday 24 October 2024 at 18:42:35 UTC+2 robert engels wrote:
> In my experience, the OPΓÇÖs issue points to a code structure problem

> and not having a deterministic lifecycle for the channels.

I agree with this strongly. I think therere should be an owner of the
channel in some way, usually the sender. Because it is the sender, or it
knows there is know more sending, it is safe for it to close the
channel, as receiving on a closed channel doesn't panic.

That said, it is unfortunate that we have to do manual garbage
collecting now, since one nice thing about go is, its garbage collector.
We get all the problems you get in other languages where you need
ownership to know when to free and avoid use after free and so on.
Channels, are very much like this.

One way to handle this as robert mentiones, may be to have something
higher up deal with the channels, provide them to the code in question.

In terms of sender should be owner/closer, it is not always as simple as
it sounds. Sometimes you need special techniques, and a whole lot of
control flow to get this right.

For example here in the io.Pipe code:
https://cs.opensource.google/go/go/+/refs/tags/go1.23.2:src/io/pipe.go;l=195

It is using an extra "done" channel to cancel sends/receives on the main
channel and does extra guard selects on it, due to select pseudo
randomness. Additionally, it has a sync.Once to prevent panic when
closing the channel twice.

tapi...@gmail.com

unread,
Oct 29, 2024, 6:31:19 AMOct 29
to golang-nuts

Nico Braun

unread,
Oct 31, 2024, 1:57:09 AMOct 31
to golang-nuts
On Tuesday 29 October 2024 at 11:31:19 UTC+1 tapi...@gmail.com wrote:
> https://github.com/golang/go/issues/21985
> https://github.com/golang/go/issues/28017
>
> Personally, I think this is an interesting idea.

Hi, thanks for sharing. I never knew you don't have to close channels,
see: https://github.com/golang/go/issues/27544#issuecomment-419515859.
Been using go for several years at this point, lol. This changes a lot,
in my opinion.

Many times, each sender can just stop sending the channel and have it
get garbage collected, when all are done. It may be even the preferred,
way. Closing the channel more more like a broadcast and not a resource
freeing operation.

Now this sentence makes a lot more sense to me:

https://pkg.go.dev/sync#Cond wrote:
> For many simple use cases, users will be better off using channels
> than a Cond (Broadcast corresponds to closing a channel, and Signal
> corresponds to sending on a channel).

After learning that you don't have to close channels, I think more like
rob pike says it in the github comment below.

https://github.com/golang/go/issues/21985#issuecomment-331622588:
> If a program sends on a closed channel, it's not managing resources
> correctly. You could argue that your proposal makes it easier to do
> that, but I would counter that it makes it too easy to construct poor
> concurrent structures.

Aniket Pandey

unread,
Oct 31, 2024, 8:29:20 AMOct 31
to golang-nuts
Hi All , 
while performing trial and error i just implemented an idea of not closing the channel  in my go-lang code , due to which my server memory was going high , sharing it just FYI
..

Ian Lance Taylor

unread,
Oct 31, 2024, 9:48:03 AMOct 31
to Aniket Pandey, golang-nuts
On Thu, Oct 31, 2024 at 5:29 AM 'Aniket Pandey' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> while performing trial and error i just implemented an idea of not closing the channel in my go-lang code , due to which my server memory was going high , sharing it just FYI

I don't know what happened in your program, but by itself calling
close on a channel will have no effect on memory usage. Channels
remain in memory until there are no more references to them and they
are garbage collected. Calling close does not affect that.

Ian

Nico Braun

unread,
Oct 31, 2024, 10:24:23 AMOct 31
to golang-nuts
I think not closing the channel has the side effect, of making it easier
to leak goroutines. If your memory is growing, its likely that there is
still a receiver who didn't realize there is nothing more to receive.
That is one thing closing a channel can do and oftentimes does, i.e.
when ranging over channels.

So when not closing channels, one needs another way to signal that all
references to that channel should be released, so the garbage collector
can collect it.

I never thought about it much but it makes sense that closing a channel,
does not free resources. Because you can still receive remaining values
from a closed channel and the zero value afterwards. So it must be
garbage collected, not matter what.

I also missed the earlier posts by Robert and Jason, who already pointed
this out. I really wish someone had told me this earlier. Although it
has an extra disclaimer on the tour. So, my bad.

https://go.dev/tour/concurrency/4
> Another note: Channels aren't like files; you don't usually need to
> close them. Closing is only necessary when the receiver must be told
> there are no more values coming, such as to terminate a range loop.

tapi...@gmail.com

unread,
Nov 2, 2024, 2:06:48 PMNov 2
to golang-nuts
On Thursday, October 31, 2024 at 10:24:23 PM UTC+8 Nico Braun wrote:
I think not closing the channel has the side effect, of making it easier
to leak goroutines. If your memory is growing, its likely that there is
still a receiver who didn't realize there is nothing more to receive.
That is one thing closing a channel can do and oftentimes does, i.e.
when ranging over channels.

So when not closing channels, one needs another way to signal that all
references to that channel should be released, so the garbage collector
can collect it.

Robert Engels

unread,
Nov 2, 2024, 2:26:31 PMNov 2
to tapi...@gmail.com, golang-nuts
Nice article. I think it over complicates the situation though and may lead to confusion. 

Some situations lead naturally to a go routine per request (web server processing) - with a fixed lifetime - others lead to a fixed count of go routines (like services) - permanence. 

Using ephemeral channels is what leads to the closing situation/complexity. 

A redesign without ephemeral channels leads to more readily understood code through less complexity. 

If you find yourself using ephemeral channels or needing to close channels at all a redesign may help. 

On Nov 2, 2024, at 1:07 PM, tapi...@gmail.com <tapi...@gmail.com> wrote:


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages