HTTP Batch从多个API获取并保存到struct

时间:2017-05-17 07:10:04

标签: go

我有以下函数用于获取URL并将数据返回到接口(例如struct / int / whatever):

var httpClient = &http.Client{Timeout: 10 * time.Second}

func getURLToTarget(url string, target interface{}) error {
    req, err := httpClient.Get(url)
    if err != nil {
        return err
    }
    defer req.Body.Close()
    return json.NewDecoder(req.Body).Decode(target)
}

然后我有几个看起来像这样的函数:

func GetCustomerByID(APIKey, cusID string) {
  cus := new(Customer)
  getURLToTarget(fmt.Sprintf("http://someurl.com/%s/customerbyid/:%s", APIKey, cusID), &cus)
}

在这种情况下会将json响应保存到这样的结构中:

type Customer struct {
  Name string
  Email string
  Address string
}

现在我的问题是,当我运行时,如何让所有这些http请求同时执行:

func main() {
  apikey := "some api key"
  GetCustomerByID(apikey, "43279843")
  GetCustomerDiscounts(apikey, "43279843")
  GetProductByID(apikey, "32124")
}

我很确定我需要使用频道,但我无法弄清楚如何...任何帮助都会非常感激

1 个答案:

答案 0 :(得分:1)

有很多方法可以达到这个目的,并且它取决于你需要发生什么。

基本的一个是使用goroutines和wg.WaitGroup并行/并发执行http调用,并在退出程序之前等待所有这些调用完成。例如:

func main() {
  apikey := "some api key"

  var wg sync.WaitGroup
  wg.Add(3)

  go func() {
    GetCustomerByID(apikey, "43279843")
    wg.Done()
  }()

  go func() {
    GetCustomerDiscounts(apikey, "43279843")
    wg.Done()
  }()

  go func() {
    GetProductByID(apikey, "32124")
    wg.Done()
  }()

  wg.Wait()
}

另一种方法是,如果要检查每个http调用的结果,请使用go通道。例如:

func GetCustomerByID(APIKey, cusID string) Customer {
  cus := new(Customer)
  getURLToTarget(fmt.Sprintf("http://someurl.com/%s/customerbyid/:%s", APIKey, cusID), &cus)
  return cus
}

func main() {
  apikey := "some api key"

  c := make(chan Customer, 3)

  go func() {
    cus := GetCustomerByID(apikey, "43279843")
    c <- cus
  }()

  go func() {
    cus := GetCustomerDiscounts(apikey, "43279843")
    c <- cus
  }()

  go func() {
    cus := GetProductByID(apikey, "32124")
    c <- cus
  }()

  // Print the result
  var i int
  for cus := range c {
    fmt.Printf("%#v\n", cus)
    i++

    if i == 3 {
      break
    }
  }
}