Description
What version of Go are you using (go version
)?
$ go version go version go1.11.4 windows/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\kjk\AppData\Local\go-build set GOEXE=.exe set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOOS=windows set GOPATH=C:\Users\kjk\go set GOPROXY= set GORACE= set GOROOT=C:\Go set GOTMPDIR= set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64 set GCCGO=gccgo set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD= set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\kjk\AppData\Local\Temp\go-build206244702=/tmp/go-build -gno-record-gcc-switches
What did you do?
Save this to e.g. t.go
:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
for i := 0; i < 256; i++ {
go func(n int) {
ch <- fmt.Sprintf("string %d", n)
}(i)
}
time.Sleep(time.Second)
close(ch)
}
and run go -race t.go
.
What did you see instead?
I see a data race reported:
> go run -race t.go
==================
WARNING: DATA RACE
Write at 0x00c00001a130 by main goroutine:
runtime.closechan()
C:/Go/src/runtime/chan.go:327 +0x0
main.main()
C:/Users/kjk/src/t.go:16 +0xb5
Previous read at 0x00c00001a130 by goroutine 231:
runtime.chansend()
C:/Go/src/runtime/chan.go:140 +0x0
main.main.func1()
C:/Users/kjk/src/t.go:12 +0xcc
Goroutine 231 (running) created at:
main.main()
C:/Users/kjk/src/t.go:11 +0x83
==================
panic: send on closed channel
goroutine 201 [running]:
main.main.func1(0xc00001a120, 0xc3)
C:/Users/kjk/src/t.go:12 +0xcd
created by main.main
C:/Users/kjk/src/t.go:11 +0x84
panic: send on closed channel
goroutine 235 [running]:
main.main.func1(0xc00001a120, 0xe5)
C:/Users/kjk/src/t.go:12 +0xcd
created by main.main
C:/Users/kjk/src/t.go:11 +0x84
exit status 2
What did you expect to see?
I didn't expect data race between close(ch)
and pending ch <- v
send.
The spec (https://golang.org/ref/spec#Channel_types) is curiously mum on the subject.
It says:
A single channel may be used in send statements, receive operations, and calls to the built-in functions cap and len by any number of goroutines without further synchronization.
By not mentioning close
it implies that one has to synchronize close
and sends.
But I wouldn't know how to synchronize those. My sends have already been dispatched and closing a channel seems like a valid (and only) way to ensure those sending goroutines don't stick forever (assumingI recover the resulting panic).
The data race seems harmless, as I'm done with this channel, but I run my tests with -race
detection enabled and this makes the test fail.