超时后退出goroutine
我正试图在go中编写一个类似于cron的程序,其中增加了一个功能,即为作业提供一个max runtime,如果某个函数超过此持续时间,则该作业应该退出。以下是我的全部代码:超时后退出goroutine,go,concurrency,goroutine,Go,Concurrency,Goroutine,我正试图在go中编写一个类似于cron的程序,其中增加了一个功能,即为作业提供一个max runtime,如果某个函数超过此持续时间,则该作业应该退出。以下是我的全部代码: package main import ( "fmt" "log" "sync" "time" ) type Job struct { ID string MaxRuntime
package main
import (
"fmt"
"log"
"sync"
"time"
)
type Job struct {
ID string
MaxRuntime time.Duration
Frequency time.Duration
Function func()
}
func testFunc() {
log.Println("OPP11")
time.Sleep(7 * time.Second)
log.Println("OP222")
}
func New(ID, frequency, runtime string, implementation func()) Job {
r, err := time.ParseDuration(runtime)
if err != nil {
panic(err)
}
f, err := time.ParseDuration(frequency)
if err != nil {
panic(err)
}
j := Job{ID: ID, MaxRuntime: r, Frequency: f, Function: implementation}
log.Printf("Created job %#v with frequency %v and max runtime %v", ID, f, r)
return j
}
func (j Job) Run() {
for range time.Tick(j.Frequency) {
start := time.Now()
log.Printf("Job %#v executing...", j.ID)
done := make(chan int)
//quit := make(chan int)
//var wg sync.WaitGroup
//wg.Add(1)
go func() {
j.Function()
done <- 0
}()
select {
case <-done:
elapsed := time.Since(start)
log.Printf("Job %#v completed in %v \n", j.ID, elapsed)
case <-time.After(j.MaxRuntime):
log.Printf("Job %#v halted after %v", j.ID, j.MaxRuntime)
// here should exit the above goroutine
}
}
}
func main() {
// create a new job given its name, frequency, max runtime
// and the function it should run
testJob := New("my-first-job", "3s", "5s", func() {
testFunc()
})
testJob.Run()
}
主程序包
进口(
“fmt”
“日志”
“同步”
“时间”
)
类型作业结构{
ID字符串
MaxRuntime.Duration
频率、时间、持续时间
函数func()
}
func testFunc(){
log.Println(“OPP11”)
时间。睡眠(7*时间。秒)
log.Println(“OP222”)
}
func新(ID、频率、运行时字符串、实现func())作业{
r、 错误:=time.ParseDuration(运行时)
如果错误!=零{
恐慌(错误)
}
f、 错误:=时间。解析持续时间(频率)
如果错误!=零{
恐慌(错误)
}
j:=作业{ID:ID,MaxRuntime:r,频率:f,函数:实现}
log.Printf(“已创建作业%#v,频率为%v,最大运行时间为%v”,ID、f、r)
返回j
}
func(j作业)运行(){
对于范围时间。勾选(j.频率){
开始:=时间。现在()
log.Printf(“作业%#v正在执行…”,j.ID)
完成:=制造(成交量)
//退出:=make(chan int)
//var wg sync.WaitGroup
//工作组.添加(1)
go func(){
j、 函数()
完成如注释中所述,整个问题在于您想要取消不可取消的函数(j.function
)的执行
没有办法“杀死一个goroutine”。goroutine以一种合作的方式工作。如果你想“杀死它”,你需要确保在该goroutine中运行的函数有一种机制,让你发出信号,它应该停止它正在做的事情并返回,让运行它的goroutine最终终止
表示函数可取消的标准方法是将context.context
作为其第一个参数:
类型作业结构{
// ...
函数func(context.context)
}
然后创建上下文并将其传递给j.Function
。由于取消逻辑仅基于超时,因此无需编写所有select…如果您无法检查@Jimb是的,我知道,函数
应该是一个通用函数,由用户传递,因此我无法添加任何c取消它内部的逻辑。没有办法杀死一个goroutine,那么问题到底是什么?根本没有办法做到这一点?甚至不使用上下文。WithTimeout
?我现在正在研究上下文。WithTimeout
只是给你一个更好的方法
go func() {
for {
select {
case <-quit:
fmt.Println("quiting goroutine")
return
default:
j.Function()
done <- 0
}
}
}()