超时时停止goroutine执行

超时时停止goroutine执行,go,goroutine,go-iris,Go,Goroutine,Go Iris,我想在超时时停止goroutine执行。但它似乎对我不起作用。我正在使用iris框架 type Response struct { data interface{} status bool } func (s *CicService) Find() (interface{}, bool) { ch := make(chan Response, 1) go func() { time.Sleep(10 * time.Second)

我想在超时时停止goroutine执行。但它似乎对我不起作用。我正在使用
iris
框架

  type Response struct {
    data   interface{}
    status bool
  }

  func (s *CicService) Find() (interface{}, bool) {

    ch := make(chan Response, 1)

    go func() {
      time.Sleep(10 * time.Second)

      fmt.Println("test")
      fmt.Println("test1")

      ch <- Response{data: "data", status: true}
    }()

    select {
    case <-ch:
      fmt.Println("Read from ch")
      res := <-ch
      return res.data, res.status
    case <-time.After(50 * time.Millisecond):
      return "Timed out", false
    }

  }
预期产出:

 Timed out
有人能指出这里缺少什么吗?它确实超时,但仍然运行goroutine来打印
test
test1
。我只想在超时时停止执行GOODUTIN。

< P> >在执行过程中没有中断GORUTIN执行的好方法。 Go使用并发的fork-join模型,这意味着您“fork”创建一个新的goroutine,然后在到达“连接点”之前无法控制该goroutine的调度方式。连接点是多个goroutine之间的某种同步。e、 g.在通道上发送值

以您的具体示例为例,这一行:

ch <- Response{data: "data", status: true}

ch控制您的goroutine处理的最佳方法是(std go库)

您可以取消goroutine中的某些内容并停止执行,而不会导致goroutine泄漏

这是一个简单的案例,可以通过超时取消

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

ch := make(chan Response, 1)

go func() {
    time.Sleep(1 * time.Second)

    select {
    default:
        ch <- Response{data: "data", status: true}
    case <-ctx.Done():
        fmt.Println("Canceled by timeout")
        return
    }
}()

select {
case <-ch:
    fmt.Println("Read from ch")
case <-time.After(500 * time.Millisecond):
    fmt.Println("Timed out")
}
ctx,cancel:=context.WithCancel(context.Background())
推迟取消
ch:=制造(chan响应,1)
go func(){
时间。睡眠(1*时间。秒)
挑选{
违约:

ch您有一个goroutine泄漏,您必须在超时之前处理一些已完成的操作以返回goroutine,如下所示:

func (s *CicService) Find() (interface{}, bool) {

    ch := make(chan Response, 1)
    done := make(chan struct{})
    go func() {
        select {
        case <-time.After(10 * time.Second):
        case <-done:
            return
        }
        fmt.Println("test")
        fmt.Println("test1")
        ch <- Response{data: "data", status: true}
    }()
    select {
    case res := <-ch:
        return res.data, res.status
    case <-time.After(50 * time.Millisecond):
        done <- struct{}{}
        return "Timed out", false
    }

}
func(s*CicService)Find()(接口{},bool){
ch:=制造(chan响应,1)
完成:=make(chan结构{})
go func(){
挑选{

案例此示例不起作用。即使您将超时设置为
case,您也永远无法读取
ch
。谢谢@MikeKlemin,用正确的行为更新了我的答案。此外,虽然睡眠只是“工作到此为止”的一个示例,但如果您确实需要睡眠(例如在轮询周期之间等待),创建一个时间通道是一个好主意,例如,
此示例仅对
Time.Sleep
tho有用。如果有一个长时间运行的函数,它不能中断它(没有提前终止)…此示例中没有打印。请使用得票最高的答案。警告:在检查ctx.Done()之前,这不会停止go例程
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

ch := make(chan Response, 1)

go func() {
    time.Sleep(1 * time.Second)

    select {
    default:
        ch <- Response{data: "data", status: true}
    case <-ctx.Done():
        fmt.Println("Canceled by timeout")
        return
    }
}()

select {
case <-ch:
    fmt.Println("Read from ch")
case <-time.After(500 * time.Millisecond):
    fmt.Println("Timed out")
}
func (s *CicService) Find() (interface{}, bool) {

    ch := make(chan Response, 1)
    done := make(chan struct{})
    go func() {
        select {
        case <-time.After(10 * time.Second):
        case <-done:
            return
        }
        fmt.Println("test")
        fmt.Println("test1")
        ch <- Response{data: "data", status: true}
    }()
    select {
    case res := <-ch:
        return res.data, res.status
    case <-time.After(50 * time.Millisecond):
        done <- struct{}{}
        return "Timed out", false
    }

}