簡體   English   中英

超時時停止執行goroutine

[英]Stop goroutine execution on timeout

我想在超時時停止執行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
 test
 test1

預期產量:

 Timed out

有人可以指出這里缺少什么嗎? 它確實超時,但仍運行goroutine來打印testtest1 我只想在超時后立即停止執行goroutine。

沒有好的方法可以在執行過程中“中斷” goroutine的執行。

Go使用並發的fork-join模型,這意味着您將“ fork”創建一個新的goroutine,然后無法控制該goroutine的調度方式,直到到達“ join point”為止。 連接點是多個goroutine之間的某種同步。 例如在通道上發送值。

以您的特定示例為例,此行:

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

……無論如何,都將能夠發送該值,因為它是一個緩沖通道。 但是超時是您創建的:

case <-time.After(50 * time.Millisecond):
  return "Timed out", false

這些超時在通道的“接收者”或“閱讀器”上, 而不在“發送者”上。 如該答案頂部所述,如果不使用某些同步技術,就無法中斷goroutine的執行。

由於超時是在goroutine從通道“讀取”中進行的,因此沒有什么可以停止在通道上發送的goroutine的執行。

控制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")
}

您有一個gouroutine泄漏,必須執行一些已完成的操作以在超時之前返回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
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM