Goroutine超时

时间:2018-07-07 12:07:48

标签: go goroutine go-iris

type Response struct {
  data   interface{}
  status bool
}

func Find() (interface{}, bool) {
  ch := make(chan Response, 1)

  go func() {
    data, status := findCicCode()
    ch <- Response{data: data, status: status}
  }()

  select {
  case response := <-ch:
    return response.data, response.status
  case <-time.After(50 * time.Millisecond):
    return "Request timed out", false
  }
}

所以,我有以上功能。基本上,findCicCode()函数调用在内部对外部服务进行了3次http调用。我在这里为这3个http调用添加了组合超时。我不能将个人超时设置为我的情况。但是,如果超过超时时间,它仍然会在后台进行api调用。

我不确定这里是否存在goroutine泄漏。如果超时,是否可以取消这些https请求?

2 个答案:

答案 0 :(得分:3)

您可以使用context.Context控制取消http请求。

// create a timeout or cancelation context to suit your requirements
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

req, err := http.NewRequest("GET", location, nil)

// add the context to each request and they will be canceled in unison
resp, err := http.Do(req.WithContext(ctx))

答案 1 :(得分:0)

如果愿意,您可以通过在通道上(主goroutine中)执行一个接收操作来创建自己的超时系统,以进行任意工作,而其他任何goroutine首先到达其发送操作-{{1} }或从事实际工作的人胜出。

这是一个完整的可运行示例/模拟。调整超时和延迟值以模拟不同的情况。通道是无缓冲的,并且在读取单个值后关闭,以允许其他goroutine在发送时退出。

time.Sleep

缓冲的通道也可以工作。您可以使用package main import( "fmt" "time" ) type Response struct { Data []byte Status int } func Wait(s int) { time.Sleep(time.Duration(s) * time.Second) } func FindWrapper(ch chan Response, delay int) { // Put real find stuff here... // Dummy response after wait for testing purposes Wait(delay) ch <- Response{[]byte("Some data..."), 200} } func main() { timeout := 3 delay := 4 ch := make(chan Response) // whoever sends to ch first wins... go func() { Wait(timeout) ch <- Response{} }() go FindWrapper(ch, delay) r := <-ch close(ch) if r.Data == nil { r.Status = 500 // or whatever you want for timeout status } fmt.Printf("Data: %s Status: %d\n", string(r.Data), r.Status) } 完成相同的操作,只需调用一次Add,然后在sync.WaitGroup之后关闭频道。

也就是说,我建议尝试使用wg.Wait()超时的JimB解决方案,因为它可能适用于您的用例,并且是一种不太复杂的解决方案。