Simple Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | func leak() { doWork := func(strings <-chan string) <-chan interface{} { completed := make(chan interface{}) go func() { defer fmt.Println("doWork exited.") defer close(completed) for s := range strings { // Do something interesting fmt.Println(s) } }() fmt.Println("end function doWork") return completed } fmt.Println("dowork") doWork(nil) // Perhaps more work is done here fmt.Println("Done.") } |
- in the doWork func with the parameter being a chan string .
- func will leak because string channel is a nil value. This means this goroutine does not clear resources, does not stop func.
- The example above may be extremely short, but in reality the func will last for a lifetime and affect the program’s resources.
Debug Resource
Install packages
- install package:
apt-get install graphviz gv
(debian) orbrew install graphviz
(mac) - install pprof:
go get -u github.com/google/pprof
- import pprof:
import _ "net/http/pprof"
- add server:
pprof
source
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package main import ( "fmt" "net/http" _ "net/http/pprof" "os" "os/signal" "syscall" ) func leak() { doWork := func(strings <-chan string) <-chan interface{} { completed := make(chan interface{}) go func() { defer func() { fmt.Println("doWork exited.") }() defer func() { close(completed) }() for s := range strings { // Do something interesting fmt.Println(s) } }() fmt.Println("end function doWork") return completed } fmt.Println("dowork") doWork(nil) // Perhaps more work is done here fmt.Println("Done.") } func main() { leak() leak() leak() go func() { http.ListenAndServe(":1234", nil) }() // sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) done := make(chan bool, 1) go func() { <-sigs done <- true }() <-done } |
- in func main, call 3 leak() functions -> in lifetime there will be 3 leaked goroutines
- start server with port 1234
- after starting the server, open another terminal
go tool pprof http://localhost:1234/debug/pprof/goroutine
and enterpng
- there will be
Generating report in profile001.png
- The result in the picture using pprof will have 3 leaks.
Video https://www.youtube.com/watch?v=e1Aa4d90nzk
Source https://github.com/ducnpdev/open-dev/blob/master/concurrency/leak.go