The Go Programming Language Specification

Close

For a channel c, the built-in function close(c) records that no more values will be sent on the channel. After calling close, and after any previously sent values have been received, receive operations will return the zero value for the channel's type without blocking.

In the channel buffer there are 5 previously sent values followed by a close.

For example,

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    iCh := make(chan int, 99)
    var wg sync.WaitGroup
    go func() {
        for i := 0; i < 5; i++ {
            wg.Add(1)
            go func(i int) {
                defer wg.Done()
                iCh <- i
            }(i)

        }
        wg.Wait()
        close(iCh)
    }()

    time.Sleep(5 * time.Second)
    fmt.Println("previously sent values", len(iCh))
    for i := range iCh {
        fmt.Printf("%v\n", i)
    }
    print("the channel should be closed by now\n")
    print("done")
}

Output:

previously sent values 5
0
1
2
3
4
the channel should be closed by now
done
Answer from peterSO on Stack Overflow
🌐
Go by Example
gobyexample.com › closing-channels
Go by Example: Closing Channels
Closing a channel indicates that no more values will be sent on it. This can be useful to communicate completion to the channel’s receivers · In this example we’ll use a jobs channel to communicate work to be done from the main() goroutine to a worker goroutine.
Discussions

How to check is a channel is closed before writing into it.
Lots of declarations that you can't, but few ever seems to explain the why of it, which I find tends to help my new hires internalize this. So, here is my suggestion for a mental model that explains this behavior: Channels are designed to efficiently communicate in one direction. The compiler could set up the memory barriers and such so that only the reader is guaranteed to observe what the writer is doing. Now, when you close a channel, that's also a write operation. So this is designed to flow from writer to reader. Wanting the reader to close and the writer to observe inverts the communication direction, from reader to writer, which inverts the safe communication direction and the compiler isn't guaranteed to have wired that up to be synchronous. When (and if) the runtime detects this, it will panic. As others have mentioned, since it's communicating from reader to writer, the right thing to do is set up your own path that way. You can have a second channel, a mutex, a wait group, etc to do so. More on reddit.com
🌐 r/golang
18
25
March 23, 2024
builtin: description of close behavior of reading from closed channel is vague
What is the URL of the page with the issue? https://pkg.go.dev/builtin#close The documentation of the built in close function states explicitly: The form x, ok := More on github.com
🌐 github.com
1
May 23, 2022
Short Read: Closing a closed channel in Go, can result in disaster
Checking first gives you a race condition. Instead, use sync.Once More on reddit.com
🌐 r/golang
15
0
April 5, 2024
Panic: send on closed channel
When I use goroutine with a single c2 channel, it’s working with no errors, on using two goroutines with same channels, I get the; panic: send on closed channel error · First, no need to apologize. Every question is welcome. Second, a tip: Surround your code by a “code fence”, like so: ... More on forum.golangbridge.org
🌐 forum.golangbridge.org
0
0
November 9, 2023
🌐
Reddit
reddit.com › r/golang › how to check is a channel is closed before writing into it.
r/golang on Reddit: How to check is a channel is closed before writing into it.
March 23, 2024 -

In the given code, I have closed a channel in generateOne and then used the same channel in the next function to write on. This will panic with a message send on closed channel. Can anyone tell me how I can make sure if the channel is closed or not before sending any data?

Note: This is a Unidirectional channel.

package main

import "time"

func generateOne(a chan<- int) {
    for i := 0; i < 10; i++ {
        a <- i
    }
    close(a)
}

func generateTwo(a chan<- int) {
    for {
        a <- 10
    }
}

func consume(a <-chan int) {
    for {
        data, ok := <-a
        if ok == false {
            break
        }
        println(data)
    }
}

func main() {
    a := make(chan int)
    go generateOne(a)
    go generateTwo(a)
    go consume(a)
    time.Sleep(1 * time.Second)
}
🌐
Medium
medium.com › @AlexanderObregon › what-go-does-when-you-close-a-channel-7a02ef356635
What Go Does When You Close a Channel | Medium
December 18, 2025 - The Go runtime represents each channel as a structure called hchan. This struct stores details like the buffer size, how many items are currently in it, where to write next, where to read from, and two queues, one for senders and one for receivers. There’s also a flag that tracks whether the channel has been closed.
🌐
Google Groups
groups.google.com › g › golang-nuts › c › SDIBFSkDlK4
A way to detect closed channel
> > > select { > case <- closedchan: > default: > close(closedchan) > } You can do that if you wrap it in a mutex so that nothing else can be doing the same thing at the same time. That's a common workaround for the fact that sometimes you want to be able to close a signal-only channel (chan struct{}) from a Close method that might be called multiple times.
🌐
GitHub
github.com › golang › go › issues › 53041
builtin: description of close behavior of reading from closed channel is vague · Issue #53041 · golang/go
May 23, 2022 - reading from the channel should read all of the available elements, but the documentation currently suggests that is not the case and should be amended. ... func TestReadClosedChannel(t *testing.T) { c := make(chan struct{}, 1) c <- struct{}{} ...
Author   golang
🌐
Antonz
antonz.org › go-concurrency › channels
Gist of Go: Channels
December 3, 2024 - If the channel is closed, the reader gets a zero value ("" for strings) and a false status. As shown, you can read from a closed channel as much as you want — it always returns a zero value and a false status.
Find elsewhere
🌐
Reddit
reddit.com › r/golang › short read: closing a closed channel in go, can result in disaster
r/golang on Reddit: Short Read: Closing a closed channel in Go, can result in disaster
April 5, 2024 - Use a separate channel shared between readers and writers that signifies when to stop. ... Oh snap! Updated the post. Thanks for pointing out the writers part. ... This is kind of a nonsense issue anyway since those workers will have to synchronize (ie "stop") anyway, close the channel then.
🌐
LabEx
labex.io › tutorials › go-how-to-prevent-reading-from-closed-channels-420252
How to prevent reading from closed channels | LabEx
When a channel is closed, any subsequent sends to the channel will panic, and receives from the channel will continue to return the channel's element type's zero value until the channel is empty.
🌐
Scaler
scaler.com › home › topics › golang › closing the channel in golang
Closing the Channel in Golang - Scaler Topics
March 31, 2023 - At last, we close mychannel using the close() function, which sets a flag indicating that no additional data will be sent to this channel. ... A closed channel still allows us to read data from it but cannot transmit data to it.
🌐
Go Forum
forum.golangbridge.org › getting help
Panic: send on closed channel - Getting Help - Go Forum
November 9, 2023 - package main import ( “fmt” “math/rand” “sync” ) func drG(wg *sync.WaitGroup, c chan int) func(int, int, int) { return func(min, max, itr int) { wg.Add(1) defer wg.Done() for i := 0; i <= itr; i++ { c <- rand…
🌐
Leapcell
leapcell.io › blog › understanding-how-to-close-channels-in-golang
Understanding How to Close Channels in Golang | Leapcell
July 25, 2025 - Closing a channel from the receiver side: It is the sender's responsibility to close the channel. Receivers should only read and not manage the channel’s lifecycle. When a channel is used within a function and all goroutines complete together. If the channel is still needed by other parts of the program. When using an unbuffered channel for a request-response model. Closing channels in Golang ...
🌐
DevGenius
blog.devgenius.io › closing-signal-channel-multiple-times-in-golang-be03521172c8
Closing signal channel multiple times in Golang | by Peter Gillich | Dev Genius
July 25, 2023 - type MultipleCloseOncefunc struct { signal chan struct{} closeCount atomic.Int32 once func() } func NewMultipleCloseOncefunc() *MultipleCloseOncefunc { signal := make(chan struct{}) return &MultipleCloseOncefunc{ //nolint:exhaustruct // closeCount zero value is good signal: signal, once: sync.OnceFunc(func() { // Introduced in Go 1.21 close(signal) }), } } func (s *MultipleCloseOncefunc) Close() { s.closeCount.Add(1) s.once() } The sync.Mutex can also be used, but it’s not optimal as sync.Once , because it always use locking and unlocking. Context with cancel handles the cancel call multiple times, so it can be used as a signal channel, too:
🌐
LogRocket
blog.logrocket.com › home › how to use go channels
How to use Go channels - LogRocket Blog
June 4, 2024 - For example, we can declare a new channel using the chan keyword, and we can close a channel using the close() function. So, if we block the code using the < - channel syntax to read from the channel, once completed, we can close it.
🌐
CopyProgramming
copyprogramming.com › howto › golang-check-if-channel-is-closed
Channel: Detecting Closure of a Channel in Golang
March 25, 2023 - By closing the channel and subsequently reading from it, you will promptly receive the default value, which is an empty string. In case of a failed link read, wg.Done() will not be called before your goroutines return. ... Why does Go panic on writing to a closed channel?, Writing to a possibly ...
🌐
Reddit
reddit.com › r/golang › drain closed channel?
r/golang on Reddit: Drain closed channel?
December 10, 2022 -

Hello there,

I have a channel chan error with a reading and writing goroutines using it. It is known in advance the writing goroutine writes to it only once then closes it. Should the reader goroutine read the error from the channel and then read again the channel closing to drain it? Or is there no need (resource usage wise) to drain a closed channel?

Code example (as requested):

ch := make(chan int)
go func(writeCh chan<- int) {
  writeCh <- 1
  close(writeCh)
}(ch)

go func(readCh <-chan int) {
  _ = <-readCh // read the 1
  _ = <-readCh // should I drain the channel??
}(ch)

Thanks!

🌐
Google Groups
groups.google.com › g › golang-nuts › c › y4UHk-Qd5go
Closed channels in select statements
November 25, 2010 - On Nov 25, 3:58 pm, Jessta <jes...@jessta.id.au> wrote: > The last read from a channel that has been closed will return a nil. > The only way to know that this nil is because the channel is closed or > not is to check for closed() after the read. > closed() won't be true until this value is read.
🌐
Vivekhigh
vhs.vivekhigh.in › knkq6gej › archive.php
golang read from closed channel
When channel is closed, value read by the goroutine is zero value of the data type of the channel. Copy code The code is as follows: ch := make (chan bool) close (ch) close (ch) // This will be panic. Detailed explanation of golang channel preface CSP: do not communicate through shared memory, ...