Run the test suite with the leakchecker library
❯ go test -v
=== RUN TestSelecting
done checking leak
--- PASS: TestSelecting (11.30s)
=== RUN TestLeakyAsync
TestLeakyAsync: leaktest.go:132: leaktest: timed out checking goroutines
TestLeakyAsync: leaktest.go:150: leaktest: leaked goroutine: goroutine 25 [chan receive]:
perform.LeakyAsync.func1(0xc00008c1e0)
/Users/jmcbride/workspace/channels-testing/perform.go:37 +0x34
created by perform.LeakyAsync
/Users/jmcbride/workspace/channels-testing/perform.go:36 +0x3f
--- FAIL: TestLeakyAsync (5.57s)
=== RUN TestContextAsync
--- PASS: TestContextAsync (0.57s)
Run the benchmarks with bench
and benchmem
to see performance
❯ go test -v -bench=. -benchmem -run "Bench*"
goos: darwin
goarch: amd64
pkg: perform
BenchmarkSelecting
BenchmarkSelecting-8 1 10114375732 ns/op 104 B/op 2 allocs/op
BenchmarkLeakyAsync
BenchmarkLeakyAsync-8 2 585489776 ns/op 704 B/op 3 allocs/op
BenchmarkContextAsync
BenchmarkContextAsync-8 2 570398894 ns/op 976 B/op 9 allocs/op
PASS
ok perform 13.655s
LeakyAsync
is roughly 2 times faster. But fails the leak checker test as the goroutine is not resolved.
Selecting
is slow because it performs a select
on every iteration of the for loop.
ContextAsync
is the best of both worlds. We don't have to do a select within the for
loop, yet we avoid a go routine
leak.