Understanding how context.AfterFunc works

96 views
Skip to first unread message

ameya loya

unread,
Sep 3, 2025, 3:15:33 PM (2 days ago) Sep 3
to golang-nuts
Hello everyone,

Recently, I came across this problem where I had to wait on a condition variable until either:
1. The condition was met
2. OR a deadline was reached

This is how I implemented a solution:

func DoSomething(ctx context.Context) error {
if _, ok := ctx.Deadline(); ok {
go broadcastOnCon(ctx)
}

cond.L.Lock()
defer cond.L.Unlock()

for <some condition is not met> {
cond.Wait()
if err := ctx.Err(); err != nil {
return err
}
}
}

func broadcastOnCon(ctx context.Context) {
<-ctx.Done()
cond.L.Lock()
defer cond.L.Unlock()
cond.Broadcast()
}

My concern is here is that I am creating way too many go routines.

I looked for help online and stumbled on this thread: https://github.com/golang/go/issues/16620

The thread ends with the reference to context.AfterFunc. The documentation for this function states:

AfterFunc arranges to call f in its own goroutine after ctx is canceled. If ctx is already canceled, AfterFunc calls f immediately in its own goroutine.

Does this mean that the AfterFunc is pretty much doing what I was doing? Or is the internal implementation different? Will my concern of creating too many go routines be mitigated if I use AfterFunc?

Thanks in advance. 

Regards,
Ameya

Jason E. Aten

unread,
11:04 AM (2 hours ago) 11:04 AM
to golang-nuts
Hi Ameya,

I can't answer your question, but I can suggest that
you steer in a different direction if possible -- away from Condition Variables.

This is one of the thorniest and hardest parts of Go, so
I'm not surprised that you have not gotten any suggestions yet.

For background, condition variables are hard to get to play well with the CSP of
channels and goroutines, as the issue you cited mentions; and 
thus in my view they should be reserved for critical
performance tuning. 

The folks writing high performance networking
usually end up using or at least very much wanting Condition 
variables in some place (bradfitz's http2, the Go ssh library from 
Google, Garrett' DeAmore's mangos/NNG), so the proposals 
to discard them seem very short sighted. 

So they are available. But they are what 
the legal folks would call "an attractive nuisance". They are like a 
swimming pool just sitting in the middle of a neighborhood--
possibly hazardous to children and so require a fence; and maybe 
warning signs.

So if you are a beginner, you will be much better served by 
avoiding Condition Variables and just using channels, select, and go 
routines. They are an exact match to solve your stated problem fragment:

select {
  case <- conditionMet:
   case <- deadlineReached:
}

This has been your warning sign. Swim at your own risk.
:)
Reply all
Reply to author
Forward
0 new messages