Better Programming

Advice for programmers.

Follow publication

How to Manage Go Channels With Range and Close

Abhishek Gupta
Better Programming
Published in
4 min readApr 20, 2020

--

Photo by Drew Beamer on Unsplash

Simple Scenario

func f1() {
c := make(chan int)
//producer
go func() {
for i := 1; i <= 5; i++ {
c <- i
time.Sleep(1 * time.Second)
}
}()
//consumer
go func() {
for x := 1; x <= 5; x++ {
i := <-c
fmt.Println("i =", i)
}
fmt.Println("press ctrl+c to exit")
}()
e := make(chan os.Signal)
signal.Notify(e, syscall.SIGINT, syscall.SIGTERM)
<-e
}
i = 1
i = 2
i = 3
i = 4
i = 5
consumer finished. press ctrl+c to exit
producer finished
^C

Goroutine Leak

//consumer
go func() {
for {
i := <-c
fmt.Println("i =", i)
}
fmt.Println("consumer finished. press ctrl+c to exit")
}()
i = 1
i = 2
i = 3
i = 4
i = 5
producer finished

'range’ and 'close’ to the Rescue

go func() {
for i := range c {
fmt.Println("i =", i)
}
fmt.Println("consumer finished. press ctrl+c to exit")
}()
go func() {
for i := 1; i <= 5; i++ {
c <- i
time.Sleep(1 * time.Second)
}
close(c)
fmt.Println("producer finished")
}()
i = 1
i = 2
i = 3
i = 4
i = 5
producer finished
consumer finished. press ctrl+c to exit

Bonus

c := make(chan int, 5)

//producer
go func() {
for i := 1; i <= 5; i++ {
c <- i
}
close(c)
fmt.Println("producer finished")
}()
go func() {
time.Sleep(5 * time.Second)
fmt.Println("consumer started")
for i := range c {
fmt.Println("i =", i)
}
fmt.Println("consumer finished. press ctrl+c to exit")
}()
producer finished
consumer started
i = 1
i = 2
i = 3
i = 4
i = 5
consumer finished. press ctrl+c to exit

Conclusion

--

--

Abhishek Gupta
Abhishek Gupta

Written by Abhishek Gupta

Principal Product Manager at Microsoft | I ❤️ Databases, Go, Kubernetes

No responses yet

Write a response