Skip to content

๐Ÿ”ฅmain้–ขๆ•ฐ็ต‚ไบ†ๆ™‚ใซ็ต‚ไบ†ใ—ใฆใ„ใชใ„goroutineใฎๅฏ่ฆ–ๅŒ–ใ‚’่กŒใ†ใƒฉใ‚คใƒ–ใƒฉใƒช

License

Notifications You must be signed in to change notification settings

usuyuki/nogolivi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

30 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ”ฅnogolivi (ๆฎ‹ใ‚Š็ซ)๐Ÿ”ฅ

SCR-20230502-nedr

ๆฎ‹ใ‚Š็ซใฏ้ฉๅˆ‡ใซๆถˆ็ซใ—ใฆใ€ 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
}

Attention

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 ใซใ‚ใ‚‹ใ‚ˆใ†ใช้ซ˜ๅบฆใช็Šถๆ…‹ใฎ็ขบ่ช

Test

ๅ˜ไฝ“ใƒ†ใ‚นใƒˆใ€็ตๅˆใƒ†ใ‚นใƒˆใจใ‚‚ใซๅฏพ่ฑกใจๅŒใ˜ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใซใŠใ„ใฆใ„ใพใ™ใ€‚

go test -shuffle=on -v -p=1 ./...

or

make test

Usage

example

example 1

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   ๐Ÿ”ฅ ===

example 2

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   ๐Ÿ”ฅ ===

example 3

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   ๐Ÿ”ฅ ===

example 4

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 ใชใฎใงใƒใƒณใƒ‰ใƒชใƒณใ‚ฐใงใใชใ„็Šถๆ…‹ใงๆญฃๅธธ

example 5

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 ใฏๅฎŸ่กŒใ•ใ‚Œใชใ„

About

๐Ÿ”ฅmain้–ขๆ•ฐ็ต‚ไบ†ๆ™‚ใซ็ต‚ไบ†ใ—ใฆใ„ใชใ„goroutineใฎๅฏ่ฆ–ๅŒ–ใ‚’่กŒใ†ใƒฉใ‚คใƒ–ใƒฉใƒช

Topics

Resources

License

Stars

Watchers

Forks