ๆฎใ็ซใฏ้ฉๅใซๆถ็ซใใฆใ no "go" living ใธใ
A library that easily completes the visualization of goroutines that are not terminated when the main function terminates.
You can visualize unterminated goroutines by adding just two lines to your existing main function.
main ้ขๆฐ็ตไบๆใซ็ตไบใใฆใใชใ goroutine ใฎๅฏ่ฆๅใ็ฐกๅๅฎ็ตใซ่กใใฉใคใใฉใชใงใใ
ๆขๅญใฎ main ้ขๆฐใซ 2 ่ก่ฟฝๅ ใใใ ใใง็ตไบใใฆใใชใ goroutine ใๅฏ่ฆๅใงใใพใใ
package main
import (
"github.com/usuyuki/nogolivi" // add
)
func main() {
defer nogolivi.Trace() // add
// your code here
}
Go 1.21 ใฎ runtime.Stack ใฎไปๆงๅคๆดใซไพๅญใใฆใใใใใ็พๅจใฏ go1.21RC2 ็ฐๅขใงใฎๅไฝใจใใฆใใพใใ
Go 1.21 ใใ runtime.Stack ใซใใใฆในใฟใใฏ ใใฌใผในๅ ใฎๅ goroutine ใไฝๆใใ goroutine ใฎ ID ใๅซใพใใใใใซใชใฃใใใจใๅฉ็จใใฆใใพใใ
https://tip.golang.org/doc/go1.21#runtime
go 1.20
goroutine 18 [runnable]:
main.main.func3()
/tmp/sandbox1046556636/prog.go:25
runtime.goexit()
/usr/local/go-faketime/src/runtime/asm_amd64.s:1598 +0x1
created by main.main
/tmp/sandbox1046556636/prog.go:25 +0x71
go 1.21
goroutine 8 [runnable]:
main.main.func3()
/tmp/sandbox910302531/prog.go:25
runtime.goexit()
/usr/local/go-faketime/src/runtime/asm_amd64.s:1650 +0x1
created by main.main in goroutine 1
/tmp/sandbox910302531/prog.go:25 +0x6a
https://go.dev/play/p/kh76htbRETg?v=gotip
main ้ขๆฐใง defer ใซใใฃใฆๅผใณๅบใใใจใงใmain ้ขๆฐ็ตไบๆใซ็ตใใฃใฆใใชใ goroutine ใๅฏ่ฆๅใใพใใ
- ๅๅญฆ่ ใซใใใใกใช goroutine ใฎ็ตไบใๅพ ใใใซ main ้ขๆฐใ็ตไบใใใฆใใพใใฑใผในใฎๆค็ฅ
- go tool trace ใซใใใใใช้ซๅบฆใช็ถๆ ใฎ็ขบ่ช
ๅไฝใในใใ็ตๅใในใใจใใซๅฏพ่ฑกใจๅใใใใฑใผใธใซใใใฆใใพใใ
go test -shuffle=on -v -p=1 ./...
or
make test
When there is some goroutines in the middle of execution when the main function is executed.
go run _examples/go_living.go
or
make ex1
go run _examples/go_living.go
Sum: 0
=== ๐ฅ Nogolivi Check Started ๐ฅ ===
โNG
Number of remaining goroutines excluding the main goroutine: 5
โ* Main Goroutine: 1
โโโฌ Goroutine 21: runnable
โ โโโ main.main.func2() (/home/user/source_code/nogolivi/_examples/go_living.go:18)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main (/home/user/source_code/nogolivi/_examples/go_living.go:18)
โโโฌ Goroutine 20: runnable
โ โโโ main.main.func2() (/home/user/source_code/nogolivi/_examples/go_living.go:18)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main (/home/user/source_code/nogolivi/_examples/go_living.go:18)
โโโฌ Goroutine 18: runnable
โโโ main.main.func2() (/home/user/source_code/nogolivi/_examples/go_living.go:18)
โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โโโ Parent: main.main (/home/user/source_code/nogolivi/_examples/go_living.go:18)
=== ๐ฅ Nogolivi Check End ๐ฅ ===
When there is a recursive goroutine in the middle of executing the main function.
go run _examples/go_living_recursively.go
or
make ex2
go run _examples/go_living_recursively.go
Sum: 0
=== ๐ฅ Nogolivi Check Started ๐ฅ ===
โNG
Number of remaining goroutines excluding the main goroutine: 5
and more
โ* Main Goroutine: 1
โโโฌ Goroutine 35: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 23: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 24: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 25: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 26: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 22: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 27: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 19: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 32: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 31: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 18: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 21: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 33: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 20: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 30: runnable
โ โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโฌ Goroutine 10: runnable
โ โโโ main.main.func2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:18)
โ โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โ โโโ Parent: main.main (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:18)
โโโฌ Goroutine 17: runnable
โโโ main.main.func1.2() (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โโโ Parent: main.main.func1 (/home/user/source_code/nogolivi/_examples/go_living_recursively.go:20)
=== ๐ฅ Nogolivi Check End ๐ฅ ===
When there is no goroutine in the middle of execution when the main function is executed.
go run _examples/no_go_living.go
or
make ex3
Sum: 15
=== ๐ฅ Nogolivi Check Started ๐ฅ ===
๐ขOK
No living goroutines except main goroutine
=== ๐ฅ Nogolivi Check End ๐ฅ ===
make ex4
go run _examples/go_living_panic.go
Sum: 0
=== ๐ฅ Nogolivi Check Started ๐ฅ ===
โNG
Number of remaining goroutines excluding the main goroutine: 5
โ* Main Goroutine: 1
โโโฌ Goroutine 9: runnable
โโโ main.main.func2() (/home/user/source_code/nogolivi/_examples/go_living_panic.go:18)
โโโ runtime.goexit() (/home/user/.asdf/installs/golang/1.21rc2/go/src/runtime/asm_amd64.s:1650)
โโโ Parent: main.main (/home/user/source_code/nogolivi/_examples/go_living_panic.go:18)
=== ๐ฅ Nogolivi Check End ๐ฅ ===
panic ใ่ตทใใใจใใใงๆญขใพใฃใฆใใพใไธใซ panic ใใใณใใชใณใฐใงใใฆใใชใใใใใใฏๅฅใฎ goroutine ใชใฎใงใใณใใชใณใฐใงใใชใ็ถๆ ใงๆญฃๅธธ
make ex5
go run _examples/no_go_living_panic.go
panic: hoge
goroutine 21 [running]:
main.main.func1(0x0?)
/home/user/source_code/nogolivi/_examples/no_go_living_panic.go:21 +0x2a
created by main.main in goroutine 1
/home/user/source_code/nogolivi/_examples/no_go_living_panic.go:19 +0x6a
exit status 2
make: *** [Makefile:12: ex5] Error 1
panic ใฎใฟ่กจ็คบใใๆญขใพใใnogolivi ใฏๅฎ่กใใใชใ