はじめに
APIデータ取得を高速化する方法として、並列処理が有効です。Goの sync.WaitGroup
を活用し、異なる2つのAPIからデータを並列で効率的に取得する方法を紹介します。具体的な例として、ユーザーデータと製品データの取得を行う架空のシナリオを設定し、直列処理と並列処理のコードを比較します。
改善前コード(直列処理)
package main
import (
"errors"
"fmt"
)
// UserData はユーザーのデータを表す架空の構造体です。
type UserData struct {
ID string
Name string
}
// ProductData は製品のデータを表す架空の構造体です。
type ProductData struct {
ID string
Title string
}
// FetchUserData は架空のユーザーデータ取得APIを模倣します。
func FetchUserData(userID string) (UserData, error) {
// ここにAPI呼び出しのロジックを記述します(省略)。
return UserData{ID: userID, Name: "John Doe"}, nil
}
// FetchProductData は架空の製品データ取得APIを模倣します。
func FetchProductData(productID string) (ProductData, error) {
// ここにAPI呼び出しのロジックを記述します(省略)。
return ProductData{ID: productID, Title: "Awesome Product"}, nil
}
// FetchData はユーザーと製品のデータを直列で取得します。
func FetchData(userID, productID string) (UserData, ProductData, error) {
user, err := FetchUserData(userID)
if err != nil {
return UserData{}, ProductData{}, err
}
product, err := FetchProductData(productID)
if err != nil {
return UserData{}, ProductData{}, err
}
return user, product, nil
}
func main() {
userID, productID := "user123", "product456"
user, product, err := FetchData(userID, productID)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("User:", user)
fmt.Println("Product:", product)
}
改善後コード(並列処理)
package main
import (
"fmt"
"golang.org/x/sync/errgroup"
)
// UserData と ProductData は前の例と同じです。
// FetchUserData と FetchProductData も前の例と同じです。
// FetchDataConcurrently はユーザーと製品のデータを並列で取得します。
func FetchDataConcurrently(userID, productID string) (UserData, ProductData, error) {
var user UserData
var product ProductData
eg := new(errgroup.Group)
// 最初のAPIを並列で呼び出し
eg.Go(func() error {
var err error
user, err = FetchUserData(userID)
return err
})
// 次のAPIを並列で呼び出し
eg.Go(func() error {
var err error
product, err = FetchProductData(productID)
return err
})
// すべてのゴルーチンが終了するのを待つ
if err := eg.Wait(); err != nil {
return UserData{}, ProductData{}, err
}
return user, product, nil
}
func main() {
userID, productID := "user123", "product456"
user, product, err := FetchDataConcurrently(userID, productID)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("User:", user)
fmt.Println("Product:", product)
}
解説
errgroup.Group
を使って非同期に2つのAPI呼び出しを並列で行い、eg.Wait()
を使ってすべてのゴルーチンが終了するのを待っています。エラーが発生した場合は、そのエラーをキャッチして適切に処理します。これにより、全体の実行時間を短縮し、より効率的なデータ取得します。