goleak-example

command module
v0.0.0-...-532ca51 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2022 License: MIT Imports: 4 Imported by: 0

README

goleak-example GoDoc Build Status GoReport Coverage Status GitHub go.mod Go version of a Go module

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.

$ 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

$ git checkout detecting

At this step we have added go.uber.org/goleak package

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

$ 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

$ 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

Documentation

Overview

Entry point for a sample

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL