处理恐慌后继续执行功能

continue the execution of a function after handled panic

我正在尝试制作一个任务调度程序,它可以在给定的时间间隔内执行任务,还可以处理发生的紧急情况。我的问题是如何在处理完 panic 后继续执行函数。

func scheduleTask(task func() error, interval time.Duration, timeout time.Duration) {
        //add waitgroup and mutex
        var wg sync.WaitGroup
        var mtx sync.Mutex
        var startTime = time.Now()
        //add each task to a goroutine and set interval and timeout to the function
        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                //check if the time is up
                if time.Since(startTime) > timeout {
                    break
                }
                defer func() {
                    if r := recover(); r != nil {
                        log.Println("Recovering from panic:", r)
                    }
                }()
                
                mtx.Lock()
                task()
                mtx.Unlock()

    
            }
        }()
        wg.Wait()
    }
    
    func main() {
        var a = 0
    
        scheduleTask(func() error {
            time.Sleep(50 * time.Millisecond)
            if a == 3 {
                a++
                panic("oops")
            }
            a++
            return nil
        }, time.Millisecond*100, time.Millisecond*1000)
    
        log.Println(a)
        if a != 10 {
            log.Fatal("Expected it to be 10")
        }
    }

恢复时会退出当前功能。在这种情况下,您可以轻松地将 task() 包裹在闭包中。

package main

import (
    "log"
    "sync"
    "time"
)

func scheduleTask(task func() error, interval time.Duration, timeout time.Duration) {
    //add waitgroup and mutex
    var wg sync.WaitGroup
    var mtx sync.Mutex
    var startTime = time.Now()
    //add each task to a goroutine and set interval and timeout to the function
    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            //check if the time is up
            if time.Since(startTime) > timeout {
                break
            }

            mtx.Lock()
            func() {
                defer func() {
                    if r := recover(); r != nil {
                        log.Println("Recovering from panic:", r)
                    }
                }()

                task()
            }()
            mtx.Unlock()

        }
    }()
    wg.Wait()
}

func main() {
    var a = 0

    scheduleTask(func() error {
        time.Sleep(50 * time.Millisecond)
        if a == 3 {
            a++
            panic("oops")
        }
        a++
        return nil
    }, time.Millisecond*100, time.Millisecond*1000)

    log.Println(a)
    if a != 10 {
        log.Fatal("Expected it to be 10")
    }
}

Playground link