https://github.com/0xvbetsun/goleak-example
Example project which represents how to use goleak module
https://github.com/0xvbetsun/goleak-example
example go golang goroutine leak
Last synced: 4 months ago
JSON representation
Example project which represents how to use goleak module
- Host: GitHub
- URL: https://github.com/0xvbetsun/goleak-example
- Owner: 0xvbetsun
- License: mit
- Created: 2022-10-05T19:05:22.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2023-02-14T14:06:47.000Z (almost 3 years ago)
- Last Synced: 2025-03-27T06:12:21.537Z (10 months ago)
- Topics: example, go, golang, goroutine, leak
- Language: Go
- Homepage:
- Size: 10.7 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# goleak-example [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![GoReport][report-img]][report] [![Coverage Status][cov-img]][cov] [![GitHub go.mod Go version of a Go module][version-img]][version]
Example project which represents how to use `goleak` module to avoid Goroutine leaks.
## Prolog
Concurrency in Go materializes itself in the form of goroutines (independent activities) and channels (used for communication). While dealing with goroutines programmer needs to be careful to avoid their leakage
### Primary reasons of leakage:
1. The goroutine is waiting to read from a channel and the data never arrives.
2. The goroutine tries to write into a channel but blocked as the existing data is never read (buffered channel).
## Step 1. The Problem
Please checkout to the `problem` branch and explore `main.go` and `main_test.go`.
After running tests `make test` and `make cover` you can recognize that tests are passing and you have 100% of test coverage.
We are running in **False Negative** test situation.
```sh
$ git checkout problem
$ make test
go test -v -race ./...
=== RUN Test_main
--- PASS: Test_main (2.00s)
PASS
ok github.com/vbetsun/goleak-example 2.446s
$ make cover
go test -race -coverprofile=cover.out -coverpkg=./... ./...
ok github.com/vbetsun/goleak-example 2.404s coverage: 100.0% of statements in ./...
go tool cover -html=cover.out -o cover.html
```
## Step 2. Detecting
Next, checkout to the `detecting` branch
```sh
$ git checkout detecting
```
At this step we have added `go.uber.org/goleak` package
```diff
import (
"bytes"
"encoding/json"
"io"
"os"
"sync"
"testing"
+
+ "go.uber.org/goleak"
)
+func TestMain(m *testing.M) {
+ goleak.VerifyTestMain(m)
+}
+
...
```
And after running test one more time - we have fixed our **False Negative** tests
```sh
$ make test
go test -v -race ./...
=== RUN Test_main
--- PASS: Test_main (2.00s)
PASS
goleak: Errors on successful test run: found unexpected goroutines:
[Goroutine 7 in state chan send, with github.com/vbetsun/goleak-example.main.func1 on top of the stack:
goroutine 7 [chan send]:
github.com/vbetsun/goleak-example.main.func1(0x1)
/goleak-example/main.go:15 +0x53
created by github.com/vbetsun/goleak-example.main
/goleak-example/main.go:14 +0x85
Goroutine 8 in state chan send, with github.com/vbetsun/goleak-example.main.func1 on top of the stack:
goroutine 8 [chan send]:
github.com/vbetsun/goleak-example.main.func1(0x2)
/goleak-example/main.go:15 +0x53
created by github.com/vbetsun/goleak-example.main
/goleak-example/main.go:14 +0x85
]
FAIL github.com/vbetsun/goleak-example 2.837s
FAIL
make: *** [test] Error 1
```
So, now we have clear understanding that we have a goroutine leak and we are already able to fix it!
## Step 3. Solution
Next, checkout to the `solution` branch
We are going to add `sync.WaitGroup` for synchronize all goroutines
Now< after running tests and coverage we will receive correct results
```sh
$ make test
go test -v -race ./...
=== RUN Test_main
--- PASS: Test_main (2.00s)
PASS
ok github.com/vbetsun/goleak-example
$ make cover
go test -race -coverprofile=cover.out -coverpkg=./... ./...
ok github.com/vbetsun/goleak-example 2.407s coverage: 100.0% of statements in ./...
go tool cover -html=cover.out -o cover.html
```
[doc-img]: https://pkg.go.dev/badge/github.com/vbetsun/goleak-example?status.svg
[doc]: https://pkg.go.dev/github.com/vbetsun/goleak-example
[ci-img]: https://github.com/vbetsun/goleak-example/actions/workflows/ci.yml/badge.svg
[ci]: https://github.com/vbetsun/goleak-example/actions/workflows/ci.yml
[report-img]: https://goreportcard.com/badge/github.com/vbetsun/goleak-example
[report]: https://goreportcard.com/report/github.com/vbetsun/goleak-example
[cov-img]: https://codecov.io/gh/vbetsun/goleak-example/branch/master/graph/badge.svg
[cov]: https://codecov.io/gh/vbetsun/goleak-example
[version-img]: https://img.shields.io/github/go-mod/go-version/vbetsun/goleak-example.svg
[version]: https://github.com/vbetsun/goleak-example