在处理 panic 后继续执行函数的代码部分。

huangapple go评论79阅读模式
英文:

continue the execution of a function after handled panic

问题

我正在尝试创建一个任务调度程序,可以在给定的时间间隔内执行任务,并且可以处理发生的 panic。我的问题是,在处理 panic 后如何继续执行函数。

func scheduleTask(task func() error, interval time.Duration, timeout time.Duration) {
    // 添加 WaitGroup 和 Mutex
    var wg sync.WaitGroup
    var mtx sync.Mutex
    var startTime = time.Now()
    // 将每个任务添加到一个 goroutine 中,并为函数设置间隔和超时时间
    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            // 检查时间是否到期
            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")
    }
}

以上是你提供的代码的翻译。

英文:

I'm trying to make a task scheduler that does tasks in the given interval and also can handle an occurring panic. My question is how can I continue executing the function after handling the 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")
    	}
    }

答案1

得分: 1

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

package main

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

func scheduleTask(task func() error, interval time.Duration, timeout time.Duration) {
	// 添加 waitgroup 和 mutex
	var wg sync.WaitGroup
	var mtx sync.Mutex
	var startTime = time.Now()
	// 将每个任务添加到 goroutine 中,并为函数设置间隔和超时
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			// 检查时间是否到期
			if time.Since(startTime) > timeout {
				break
			}

			mtx.Lock()
			func() {
				defer func() {
					if r := recover(); r != nil {
						log.Println("从 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("糟糕")
		}
		a++
		return nil
	}, time.Millisecond*100, time.Millisecond*1000)

	log.Println(a)
	if a != 10 {
		log.Fatal("期望值为 10")
	}
}

Playground 链接

英文:

When recovering you will exit the current function. In this case you can easily wrap the task() in a closure.

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

huangapple
  • 本文由 发表于 2022年5月11日 04:01:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/72192332.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定