Is there a comparable function like java Thread.isAlive()
for goroutine?
I am trying to spawn some goroutine that is meant to be long living threads, but I am afraid that goroutine can die mid process, is there a check that I can do in my main thread to see if goroutine is alive?
Is there a comparable function like java Thread.isAlive() for goroutine?
No. You have to redesign your solution. Goroutines have no identity and cannot be accessed in any way.
Yes, goroutine has a unique ID in golang, you can find it in runtime package.
But goroutineID should not be used unless debug.
If you want to monitor one goroutine, the better way is channel or log
No,
You may implement a channel/Sync method yourself, to check if specific goroutine is alive.
Also you may get the number of Goroutines using runtime.NumGoroutine()
, like so:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
fmt.Println(runtime.NumGoroutine()) // 1
go fun2()
fmt.Println(runtime.NumGoroutine()) // 2
go fun3()
fmt.Println(runtime.NumGoroutine()) // 3
time.Sleep(120 * time.Millisecond)
fmt.Println(runtime.NumGoroutine()) // 2
}
func fun3() {
time.Sleep(100 * time.Millisecond)
}
func fun2() {
select {}
}
The best way is not to know if it's till alive but to know when it dies so you can restart it.
You can do that by setting a defer
with a recover
on your goroutine which would write to a channel signaling the death of the goroutine. Then on the main goroutine, you read from that channel, and whenever something is read, you restart a goroutine. You could identify wich goroutine failed by returning a struct containing the goroutine id and the error.
Example:
package main
import "fmt"
// number of desired workers
const nWorkers = 10
func main() {
// make a buffered channel with the space for my 10 workers
workerChan := make(chan *worker, nWorkers)
for i := 0; i < nWorkers; i++ {
i := i
wk := &worker{id: i}
go wk.work(workerChan)
}
// read the channel, it will block until something is written, then a new
// goroutine will start
for wk := range workerChan {
// log the error
fmt.Printf("Worker %d stopped with err: %s", wk.id, wk.err)
// reset err
wk.err = nil
// a goroutine has ended, restart it
go wk.work(workerChan)
}
}
type worker struct {
id int
err error
}
func (wk *worker) work(workerChan chan<- *worker) (err error) {
// make my goroutine signal its death, wether it's a panic or a return
defer func() {
if r := recover(); r != nil {
if err, ok := r.(error); ok {
wk.err = err
} else {
wk.err = fmt.Errorf("Panic happened with %v", r)
}
} else {
wk.err = err
}
workerChan <- wk
}()
// do something
// ...
return err
}