atomically closing termination channels in Go

done := make(chan struct{})for {
select {
case <-done:
return
case job := <-jobs:
// execute job
}
}

Approaches to closing this done channel

Option 1: using a mutex

c.mu.Lock()
if c.err != nil {
c.mu.Unlock()
return // already canceled
}
c.err = err
if c.done == nil {
c.done = closedchan
} else {
close(c.done)
}

Option 2: using sync.Once

var once sync.Onceonce.Do(func() {
close(done)
})

Option 3: Using select

import (
"sync"
"testing"
)
func TestClose(t *testing.T) {
done := make(chan struct{})
closer := func() {
select {
case <-done:
default:
close(done)
}
}
wg := sync.WaitGroup{}
wg.Add(10000)
for i := 0; i < 10000; i++ {
go func() {
wg.Done()
closer()
}()
}
wg.Wait()
}

What about channels where you communicate data?

--

--

--

software engineer at auth0, writing code for humans, with humans.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

ReactNative Vs Flutter to build your cross-platform mobile app in 2020

The new architecture of the TezEdge node — bridging the gap between formal specification and…

LeetCode - Shortest Distance from All Buildings

Adding a Basic Search Form in Rails

Scaling to New Heights

How should you pin your npm dependencies and why?

What Is Container Orchestration? Describing In 200 Words

7 VSCode extensions to make development comfortable

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Cyril David

Cyril David

software engineer at auth0, writing code for humans, with humans.

More from Medium

Generating JSON data from Go (Golang) structs with Go2JSON

Getting started with GO Programming Language — Part Two

Plugging logrus into go-retryablehttp

Golang — basic unit testing and benchmarking