2017-05-17 43 views
0

我有以下的功能,我用它來獲得一個URL和數據返回的接口(如結構/ INT /不管):HTTP批次從多個API獲取並保存到結構

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

我敢肯定,我需要使用渠道,但我無法弄清楚如何..任何幫助將是非常感謝

+4

那麼,Go有一個很好的關鍵字來同時運行的東西,它被稱爲'go'。我建議通過Tour of Go解決這個問題,這個解決方案要比任何答案都好。 – Volker

+0

假設你參考了tour.golang.org/concurrency,那麼我認爲這是第一個任何人(包括我自己)去..但在我的情況下(以及我讀過的在線文章是不夠的) – fisker

+0

假設你的意思是簡單地在函數調用前添加'go',那麼我99%確定它不會導致批量拖動,所以它仍然會發出X請求(在這種情況下爲3),而不是通過1請求 – fisker

回答

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

另一種方法是使用go通道,如果你想檢查每個http調用的結果。例如:

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 
    } 
    } 
} 
+0

也許我是愚蠢的,但我認爲這種方式仍然會發送3請求,而不是1?我認爲有一個與批量http請求相關的概念,以便不發送X個單獨的請求(與您的答案並行發生),那麼您只需發送一個請求來完成這一切? – fisker

+0

對不起,也許我沒有得到你的要求,在這裏你想只有一個http呼叫3個不同的http請求? – Maiah

+0

是的,但@mkopriva說這是不可能的(至少不是我認爲的那樣),所以我想你的答案在情況下達到最好的結果:) – fisker