0
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 请求?

4

2 回答 2

3

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

// 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))
于 2018-07-07T13:14:54.630 回答
0

如果您愿意,您可以通过在通道上(在主 goroutine 中)进行单个接收操作来为任意工作创建自己的超时系统,并且任何其他 goroutine 首先到达其发送操作 -time.Sleep或者做实际工作的那个 - - 胜利。

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

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)
}

缓冲通道也可以。sync.WaitGroup您可以通过只调用 Add 一次然后在 之后关闭通道来完成同样的事情wg.Wait()

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

于 2018-07-07T13:36:34.857 回答