Search code examples
multithreadinggotimergoroutine

How to "keep main thread running" even though routine has "runtime error" occurred in Golang?


I am new to Goland and I did Java in the past. I've written a Golang function to calculate the integer number part of the result. What I am thinking is using a timer to do the calculation and generate the random number. But one problem I met is if the routine has some error, the main thread will stop. Is there any way to keep the main thread running? Even though there are errors in routine?

Below is the code for test:

func main() {
    ticker := time.NewTicker(1*1000 * time.Millisecond)
    for _ = range ticker.C {
        rand.Seed(time.Now().Unix())
        divisor := rand.Intn(20)
        go calculate(divisor)
    }
}

func calculate(divisor int){
    result:= 100/divisor
    fmt.Print("1/"+strconv.Itoa(divisor)+"=")
    fmt.Println(result)
}

As the error handling for Golang really confused me, as what I am thinking is the error occurs in the "thread", the main function is just responsible to create the thread and assign task, it should never mind whether there are exceptions occurs in the "threads" and main should always keep going. If I do this in Java, I could use try catch to surround with

try{
    result = 1/divisor;
}
catch(Exception e){
    e.printTrace();
}

even every time I give divisor a 0 value in a separate thread, the main progress will not exit, but for Golang, I think

go calculate(divisor)

is opening a new "thread" and run calculate inside the "thread", but why the main progress will quit. Is there any possible method to prevent the main progress to quit?

Thanks.


Solution

  • use the defer/ recover feature

    package main
    
    import (
        "fmt"
        "time"
        "math/rand"
    )
    
    func main() {
    
        ticker := time.NewTicker(1*1000 * time.Millisecond)
        for _ = range ticker.C {
            rand.Seed(time.Now().Unix())
            divisor := rand.Intn(20)
            go calculate(divisor)
        }
    fmt.Println("that's all")
    }
    
    
    
    func calculate(divisor int){
    defer func() {
            if r := recover(); r != nil {
                fmt.Println("Recovered in f", r)
            }
        }()
        result:= 100/divisor
        fmt.Printf("1/%d=", divisor)
        fmt.Println(result)
    }