在超时时停止执行goroutine

Pan*_*lde 4 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)

      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
    }

  }
Run Code Online (Sandbox Code Playgroud)

输出:

 Timed out
 test
 test1
Run Code Online (Sandbox Code Playgroud)

预期产出:

 Timed out
Run Code Online (Sandbox Code Playgroud)

有人能指出这里缺少什么吗?它确实超时但仍然运行goroutine打印testtest1.我只想在超时后立即停止执行goroutine.

Ole*_*sur 9

控制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")
}
Run Code Online (Sandbox Code Playgroud)


Zak*_*Zak 8

没有好的方法可以在执行过程中"中断"执行goroutine.

Go使用并发的fork-join模型,这意味着你"fork"创建一个新的goroutine,然后在你到达"join point"之前无法控制goroutine的调度方式.连接点是多个goroutine之间的某种同步.例如,在频道上发送值.

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

ch <- Response{data: "data", status: true}
Run Code Online (Sandbox Code Playgroud)

...无论如何都能发送值,因为它是一个缓冲通道.但是你创建的超时时间是:

case <-time.After(50 * time.Millisecond):
  return "Timed out", false
Run Code Online (Sandbox Code Playgroud)

这些超时位于频道的"接收者"或"读者",而不是 "发送者".如本答案顶部所述,没有使用某些同步技术就无法中断goroutine的执行.

因为超时是从频道"读取"的,所以没有什么可以阻止在频道上发送的goroutine的执行.