---
title: "GoでGemini APIを呼び出す実装手順｜SDKとエンドポイントURL【2026年8月版】"
url: "https://www.issoh.co.jp/tech/details/2760/"
published: 2024-06-25
updated: 2026-10-22
categories: ["Gemini"]
publisher: "株式会社一創"
---

# GoでGemini APIを呼び出す実装手順｜SDKとエンドポイントURL【2026年8月版】

GoからGemini APIを叩こうとして最初に迷うのは、検索で出てくるサンプルコードがどの世代のものか判別できない点です。`github.com/google/generative-ai-go` を使う記事はすでにサポートが終了したSDKを前提にしており、そのまま写しても最新モデルは呼べません。この記事では現行SDK `google.golang.org/genai` v1.66.0 の実コードと、SDKを介さずエンドポイントURLを直接叩く実装の両方を、2026年8月時点の一次情報にもとづいて整理します。

## まとめ

結論として、GoでGemini APIを使うなら選択肢は**現行SDK `google.golang.org/genai` の一択**です。旧SDK `github.com/google/generative-ai-go` は公式READMEで2025年11月30日にサポート終了が明記されており、v0.20.1（2025年5月2日）を最後に更新が止まっています。

ただし2026年8月時点では、Googleが「新規開発の推奨」と位置づけるInteractions APIにGo SDKが追随していません。Interactions APIをGoから使うなら `net/http` でエンドポイントを直接叩く必要があり、SDKで完結する `GenerateContent` との使い分けが実装判断の分かれ目になります。エンドポイントURLの構造、モデルIDの選び方、goroutineで並行呼び出しするときの制約まで、順に見ていきます。

Gemini API自体の定義、できること、料金、始め方は[Gemini APIとは？できること・料金・始め方とInteractions APIの最小コード](https://www.issoh.co.jp/tech/details/18759/)で整理しています。この記事はGoから呼ぶ実装に絞ります。

## 旧SDK generative-ai-go のサポート終了と移行先

日本語の検索結果に残るGo向けサンプルの多くは `github.com/google/generative-ai-go/genai` を import しています。このリポジトリのREADMEは冒頭が「\[Deprecated\] Google AI Go SDK for the Gemini API」で始まり、サポート方針として次の2点を明記しています。

- Limited Maintenance：開発は重大なバグ修正のみに限定され、新機能は追加されない
- End-of-Life Date：バグ修正を含むすべてのサポートが2025年11月30日で恒久的に終了する

この日付には注意が必要です。EOL日は当初2025年8月31日と告知され、2025年6月に9月30日へ、2025年8月に11月30日へと二度延長されています。pkg.go.devやモジュールのアーカイブが表示するREADMEは最終タグ（v0.20.1、2025年5月2日）時点の内容なので、そこを読むと廃止済みの「8月31日」を掴みます。現行の日付を確認したいときは、リポジトリのmainブランチのREADMEを直接見てください。

移行先は `google.golang.org/genai`（リポジトリは `github.com/googleapis/go-genai`）です。CHANGELOG上2026年7月28日付の v1.66.0 まで、週次に近いペースで更新が続いています。Gemini 2.0以降のモデル追加や新機能は、すべて新SDK側にしか入りません。

見分け方は import パスだけで足ります。`github.com/google/generative-ai-go` と書かれた記事は2025年前半以前の情報なので、モデルIDもAPI仕様も現行と一致しないと考えて読み飛ばして構いません。Go本体のバージョン管理と合わせて棚卸しする場合は、[Go 1.27の新機能・変更点まとめ](/tech/details/10416/)で移行時の言語側の変更点も確認しておくと手戻りが減ります。

## Gemini APIをGoから呼ぶ最小実装

### SDKの導入とAPIキーの読み込み優先順位

導入はモジュールを追加するだけです。go-genai の go.mod は `go 1.24` を要求するため、それより古いGoでは `go get` の時点で弾かれます。

```
go get google.golang.org/genai
```

APIキーは `ClientConfig.APIKey` に直接渡すほか、環境変数からも読めます。ここに実装上の注意点があります。SDKは `GOOGLE_API_KEY` と `GEMINI_API_KEY` の**両方**を参照し、両方がセットされている場合は警告ログを出したうえで `GOOGLE_API_KEY` を採用します。

```
func getAPIKeyFromEnv(envVars map[string]string) string {
    googleAPIKey := envVars["GOOGLE_API_KEY"]
    geminiAPIKey := envVars["GEMINI_API_KEY"]
    if googleAPIKey != "" && geminiAPIKey != "" {
        log.Printf("Warning: Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.")
    }
    if googleAPIKey != "" {
        return googleAPIKey
    }
    return geminiAPIKey
}
```

CI環境で他のGoogle系サービス用に `GOOGLE_API_KEY` を設定していると、`GEMINI_API_KEY` に正しいキーを入れたつもりでも別のキーが使われて401になります。安全なのは、どちらか一方だけを定義しておくことです。

### GenerateContentの最小コード

テキスト生成の最小構成は次のとおりです。`genai.Text()` は文字列を `[]*genai.Content` に包むヘルパー、`resp.Text()` は候補の先頭からテキストを取り出すヘルパーです。

```
package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()

    // APIKey を省略すると GOOGLE_API_KEY、無ければ GEMINI_API_KEY を読む
    client, err := genai.NewClient(ctx, &genai.ClientConfig{
        Backend: genai.BackendGeminiAPI,
    })
    if err != nil {
        log.Fatalf("client init: %v", err)
    }

    resp, err := client.Models.GenerateContent(ctx,
        "gemini-2.5-flash",
        genai.Text("Goの並行処理をエンジニア向けに3行で説明して"),
        nil,
    )
    if err != nil {
        log.Fatalf("generate: %v", err)
    }
    fmt.Println(resp.Text())
}
```

`Backend` には `BackendUnspecified`・`BackendGeminiAPI`・`BackendVertexAI`・`BackendEnterprise` の4つが定義されています。ゼロ値は `BackendUnspecified`、つまり `Backend` を書かなかった場合の既定値です。このとき環境変数 `GOOGLE_GENAI_USE_VERTEXAI` が `1` か `true` なら Vertex AI、それ以外なら Gemini API が選ばれます。`BackendEnterprise` はクライアント生成時に `BackendVertexAI` へ正規化される別名なので、実際に到達するバックエンドは2系統です。Google Cloud側の認証を使う場合のみ Vertex AI 系を選び、APIキー1本で動かすなら `BackendGeminiAPI` を明示してください。

## Gemini APIのエンドポイントURL構造

### generateContentとstreamGenerateContentのURL

SDKが内部で組み立てるURLは、ベースURL・APIバージョン・リソースパスの3要素です。go-genai のソース上では、Gemini APIバックエンドのベースURLが `https://generativelanguage.googleapis.com/`、APIバージョンの既定値が `v1beta`、リソースパスが `{model}:generateContent` と定義されており、モデル名には `models/` 接頭辞が自動で付きます。組み上がる完全なURLは次の形です。

| 用途               | メソッド | URL                                                                                           |
| ---------------- | ---- | --------------------------------------------------------------------------------------------- |
| 一括生成             | POST | https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent               |
| ストリーミング          | POST | https://generativelanguage.googleapis.com/v1beta/models/{model}:streamGenerateContent?alt=sse |
| Interactions API | POST | https://generativelanguage.googleapis.com/v1beta2/interactions                                |
| Vertex AI経由      | POST | https://{location}-aiplatform.googleapis.com/v1beta1/…                                        |

認証はクエリパラメータではなくヘッダで渡すのが現行の作法です。SDKも `x-goog-api-key` ヘッダにAPIキーをセットしています。URLに `?key=` を付ける旧来の書き方はログやリファラにキーが残るため避けてください。

### net/httpだけで叩く最小クライアント

SDKを入れずに標準ライブラリだけで完結させたい場合、必要なのは構造体2つとPOST1回です。バッチ処理やLambda相当の環境でバイナリサイズを抑えたいときはこちらが有利になります。

```
package main

import (
    "bytes"
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "os"
    "time"
)

const endpoint = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"

type genReq struct {
    Contents []content `json:"contents"`
}
type content struct {
    Parts []part `json:"parts"`
}
type part struct {
    Text string `json:"text"`
}
type genResp struct {
    Candidates []struct {
        Content content `json:"content"`
    } `json:"candidates"`
}

func main() {
    body, err := json.Marshal(genReq{Contents: []content{{Parts: []part{{Text: "ping"}}}}})
    if err != nil {
        log.Fatal(err)
    }

    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(body))
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("x-goog-api-key", os.Getenv("GEMINI_API_KEY"))

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        log.Fatalf("gemini: status %d", resp.StatusCode)
    }
    var out genResp
    if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
        log.Fatal(err)
    }
    if len(out.Candidates) == 0 || len(out.Candidates[0].Content.Parts) == 0 {
        log.Fatal("gemini: no content (safety filter などで空になる)")
    }
    fmt.Println(out.Candidates[0].Content.Parts[0].Text)
}
```

末尾の空チェックを省くと、安全性フィルタでブロックされた応答を受けたときに `index out of range` でpanicします。HTTPステータスは200で返るため、ステータスコードの確認だけでは防げません。候補が0件になるパターンと、候補は1件返るのに `Parts` が空になるパターンの両方があるので、条件は2つ必要です。

## GA済みInteractions APIとGo SDK未対応というギャップ

2026年8月時点で、Gemini APIの公式ドキュメントは全ページ共通のバナーで「Interactions APIが一般提供（GA）になった。最新の機能とモデルを使うにはこのAPIを推奨する」と告知しています。移行ガイドも「`generateContent` は引き続き完全にサポートされるが、新規開発にはInteractions APIを推奨する」と明言しています。

問題は、この推奨がGoにそのまま適用できない点です。公式のGetting startedページは「Interactions APIはPythonとJavaScriptのSDK、およびRESTで利用できる」と対応言語を明示しており、Goは含まれていません。同ページの全文に `google.golang.org/genai` という文字列は一度も登場しません。移行ガイドのサンプルもPython・JavaScript・RESTの3種類だけです。go-genai v1.66.0 の `Client` 構造体が公開しているサービスは `Models`・`Chats`・`Files`・`Batches` など10種ですが、そのなかにInteractionsに相当するサービスはありません。

したがってGoの実装判断は明確です。**会話履歴のサーバー側保持や複数ステップのツール実行が要件でないなら、当面は `GenerateContent` のままで問題ありません**。SDKの型と再試行・認証の面倒を捨ててまでInteractions APIへ移る理由は、Go単体では現時点で薄いからです。逆に、履歴をアプリ側のDBに持たせたくない場合は自前で叩く価値があります。Interactions APIは `previous_interaction_id` を渡すだけでサーバー側が文脈を引き継ぐため、`contents` 配列を毎回組み直すコードが不要になります。ただし引き継がれるのは入出力の履歴だけです。`tools`・`system_instruction`・`generation_config` はインタラクション単位の指定なので、継続ターンでも毎回送り直す必要があります。

```
package main

import (
    "bytes"
    "context"
    "encoding/json"
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "time"
)

const interactionsURL = "https://generativelanguage.googleapis.com/v1beta2/interactions"

type interactionReq struct {
    Model                 string `json:"model"`
    Input                 string `json:"input"`
    PreviousInteractionID string `json:"previous_interaction_id,omitempty"`
}

type interactionResp struct {
    ID     string `json:"id"`
    Status string `json:"status"`
    Steps  []struct {
        Type    string `json:"type"`
        Status  string `json:"status"`
        Content []struct {
            Type string `json:"type"`
            Text string `json:"text"`
        } `json:"content"`
    } `json:"steps"`
}

func (r interactionResp) outputText() string {
    var buf bytes.Buffer
    for _, s := range r.Steps {
        if s.Type != "model_output" {
            continue
        }
        for _, c := range s.Content {
            if c.Type == "text" {
                buf.WriteString(c.Text)
            }
        }
    }
    return buf.String()
}

func createInteraction(ctx context.Context, in interactionReq) (interactionResp, error) {
    var out interactionResp
    body, err := json.Marshal(in)
    if err != nil {
        return out, err
    }
    req, err := http.NewRequestWithContext(ctx, http.MethodPost, interactionsURL, bytes.NewReader(body))
    if err != nil {
        return out, err
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("x-goog-api-key", os.Getenv("GEMINI_API_KEY"))

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return out, err
    }
    defer resp.Body.Close()
    if resp.StatusCode != http.StatusOK {
        b, _ := io.ReadAll(resp.Body)
        return out, fmt.Errorf("interactions: status %d: %s", resp.StatusCode, b)
    }
    return out, json.NewDecoder(resp.Body).Decode(&out)
}

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
    defer cancel()

    first, err := createInteraction(ctx, interactionReq{
        Model: "gemini-3.6-flash",
        Input: "私の名前は山田です",
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(first.outputText())

    // 履歴はサーバー側が保持する。contents 配列を組み直す必要はない
    second, err := createInteraction(ctx, interactionReq{
        Model:                 "gemini-3.6-flash",
        Input:                 "私の名前は？",
        PreviousInteractionID: first.ID,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(second.outputText())
}
```

レスポンスは `generateContent` の `candidates` 構造ではなく、実行ステップが時系列で並ぶ `steps` 配列です。ここで取り違えやすいのが、POSTの応答に入るのは `model_output` や `function_call` といったモデル側のステップだけという点です。ユーザー入力を含む全履歴が欲しい場合は `GET /v1beta2/interactions/{id}` を呼びます。テキストの取り出しは `model_output` 型のステップだけを走査すれば足ります。

なお `steps` 配列は2026年5月の破壊的変更で旧 `outputs` 配列を置き換えたものです。旧スキーマは2026年6月8日に削除され、同時に `response_mime_type` も `response_format` へ統合されました。移行期は `Api-Revision` リクエストヘッダでスキーマを固定できますが、これから書くコードは新スキーマ前提で構いません。SDKが対応していない以上この変換は自作するしかないので、上記のような小さなアダプタ関数に閉じ込めておくと、後日SDKが対応したときの差し替えが1箇所で済みます。

## モデルIDの選定と2026年8月時点の提供状況

モデルIDは文字列で渡すため、存在しないIDを書いてもコンパイルは通り、実行時に404で落ちます。公式の廃止情報ページから、シャットダウン日が未告知＝当面使える安定版を抜き出すと次のとおりです。

| モデルID                 | リリース日      | シャットダウン日（最短）     | 推奨移行先                 |
| --------------------- | ---------- | ---------------- | --------------------- |
| gemini-3.6-flash      | 2026-07-21 | 未告知              | –                     |
| gemini-3.5-flash      | 2026-05-19 | 未告知              | –                     |
| gemini-3.5-flash-lite | 2026-07-21 | 未告知              | –                     |
| gemini-2.5-pro        | 2025-06-17 | 未告知              | –                     |
| gemini-2.5-flash      | 2025-06-17 | 未告知              | –                     |
| gemini-2.5-flash-lite | 2025-07-22 | 未告知              | –                     |
| gemini-3.1-flash-lite | 2026-05-07 | 2027-05-07       | gemini-3.5-flash-lite |
| gemini-2.0-flash      | 2025-02-05 | 2026-06-01（経過済み） | gemini-3.6-flash      |
| gemini-2.0-flash-lite | 2025-02-25 | 2026-06-01（経過済み） | gemini-3.1-flash-lite |

実装の起点としては、SDK公式サンプルが既定値に採用している `gemini-2.5-flash` が扱いやすく、レスポンス構造の互換情報も揃っています。最新世代の推論性能が要るなら `gemini-3.6-flash` へ切り替えます。注意すべきは `gemini-2.0-flash` 系です。公式が示すシャットダウン日2026年6月1日をすでに過ぎています。この日付は公式ページが明記するとおり「廃止されうる最も早い日」で確定日ではないため、現時点でまだ応答が返る可能性はありますが、いつ停止されてもおかしくない状態です。古いサンプルからこのモデルIDをそのまま写すのは避けてください。世代ごとの位置づけを整理したい場合は[Gemini 3のラインアップと3.1への進化](/tech/details/10092/)、API単価まで含めて比較するなら[Gemini 3.1 Proの料金とAPI単価](/tech/details/11077/)が参考になります。

## ストリーミング応答のrange-over-func受信

長文生成で体感待ち時間を減らすなら、`GenerateContentStream` を使います。戻り値は `iter.Seq2[*genai.GenerateContentResponse, error]` で、Go 1.23で入ったrange-over-funcにそのまま渡せます。旧SDKのイテレータのように `iterator.Done` を判定するコードは不要になりました。

```
stream := client.Models.GenerateContentStream(ctx,
    "gemini-2.5-flash",
    genai.Text("Goのcontextパッケージの使いどころを箇条書きで"),
    nil,
)
for chunk, err := range stream {
    if err != nil {
        log.Fatalf("stream: %v", err)
    }
    fmt.Print(chunk.Text())
}
```

ループ内で `break` すると、SDK側は残りのレスポンスを読まずに接続を閉じます。ただし打ち切り時点までに生成されたトークンは課金対象になり得るため、途中打ち切りをコスト削減策として当てにしないでください。削るなら入力側です。トークン量を抑える考え方は[コンテキストウィンドウのトークン上限と溢れ対策](/tech/details/16061/)にまとめてあります。

## goroutine並行呼び出しとレート制限の設計

Goを選ぶ理由の多くは並行処理です。ただしGemini API側のレート制限はRPM（1分あたりリクエスト数）・TPM（1分あたり入力トークン数）・RPD（1日あたりリクエスト数）の3軸で、いずれか1つを超えた時点でエラーになります。しかも**制限はAPIキー単位ではなくプロジェクト単位**なので、キーを複数発行して回避することはできません。RPDは太平洋時間の深夜にリセットされます。

したがって、スライスの要素数だけgoroutineを起動する素朴な実装は避けてください。同時実行数を固定する形にします。`errgroup.SetLimit` を使うと、ワーカープールを自前で書かずに上限を宣言できます。`errgroup` は標準ライブラリではないため `go get golang.org/x/sync` が別途必要です。

```
func summarizeAll(ctx context.Context, client *genai.Client, docs []string, limit int) ([]string, error) {
    results := make([]string, len(docs))

    g, ctx := errgroup.WithContext(ctx)
    g.SetLimit(limit) // RPM を超えないよう同時実行数を固定する

    for i, doc := range docs {
        g.Go(func() error {
            resp, err := client.Models.GenerateContent(ctx,
                "gemini-2.5-flash",
                genai.Text("次の文書を1行で要約して:\n"+doc),
                nil,
            )
            if err != nil {
                return fmt.Errorf("doc %d: %w", i, err)
            }
            results[i] = resp.Text() // インデックス指定なので排他制御は不要
            return nil
        })
    }
    if err := g.Wait(); err != nil {
        return nil, err
    }
    return results, nil
}
```

ループ変数 `i`・`doc` をクロージャ内でそのまま参照できるのは、Go 1.22でループ変数がイテレーションごとに新しい変数になったためです。`go.mod` の `go` ディレクティブが1.21以前のモジュールでは従来の共有セマンティクスが適用され、全goroutineが最後の要素を見る古典的なバグに戻ります。go-genai は `go 1.24` を要求するので通常は問題になりませんが、既存モジュールへ後付けする場合は `go.mod` の宣言を確認してください。

同時実行数の具体値については、公式のレート制限ページにモデル別のRPM実数値の表は掲載されておらず、AI StudioのRate Limitページで各自の値を確認する案内になっています。ネット上の「無料枠は15 RPM」といった数値は世代ごとに変わるため、実装時は自分のプロジェクトの表示値を参照してください。加えて、支出ベースの制限が10分のローリング窓で別途かかります（Freeは対象外、Tier 1は10ドル、Tier 2と3は200ドル）。この上限に触れると `429 RESOURCE_EXHAUSTED` が返るため、並行数を上げるほど詰まりやすくなります。

## APIErrorの判定と再試行の実装

Gemini APIのエラーは、SDKが `genai.APIError` という構造体で返します。フィールドは `Code`（HTTPステータス）・`Message`・`Status`・`Details` の4つです。

ここに `errors.As` の落とし穴があります。SDKの内部実装は `APIError{...}` を**値型**で返しており、ポインタでは返しません。そのため `var apiErr *genai.APIError` のようにポインタ型で受けると `errors.As` は常に false を返し、リトライ判定が丸ごと無効化されます。値型で受けるのが正解です。

```
func generateWithRetry(ctx context.Context, client *genai.Client, prompt string) (string, error) {
    backoff := time.Second
    for attempt := 0; attempt < 4; attempt++ {
        resp, err := client.Models.GenerateContent(ctx, "gemini-2.5-flash", genai.Text(prompt), nil)
        if err == nil {
            return resp.Text(), nil
        }

        // APIError は値型で返る。*genai.APIError で受けると errors.As が一致しない
        var apiErr genai.APIError
        if !errors.As(err, &apiErr) {
            return "", err
        }
        if apiErr.Code != 429 && apiErr.Code != 503 {
            return "", fmt.Errorf("gemini %d %s: %s", apiErr.Code, apiErr.Status, apiErr.Message)
        }
        select {
        case <-ctx.Done():
            return "", ctx.Err()
        case <-time.After(backoff):
        }
        backoff *= 2
    }
    return "", errors.New("gemini: retry limit exceeded")
}
```

再試行の対象は429（レート制限・クォータ超過）と503（一時的な過負荷）に限定します。400番台の入力エラーや403の権限エラーは何度投げても同じ結果になるため、即座に返して呼び出し元にエラーを伝えるべきです。再試行しない判断を明示的に書いておくと、無駄な待ち時間とトークン消費を避けられます。503が継続する場合の切り分け手順は[503エラーの原因切り分けと復旧](/tech/details/13172/)が実務の手順として使えます。

## よくある質問

**Q. Gemini APIのエンドポイントURLは何ですか。**  
A. テキスト生成は `https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent` です。ストリーミングは末尾を `:streamGenerateContent?alt=sse` に変えます。Interactions APIだけはバージョンが異なり `/v1beta2/interactions` になります。認証は `x-goog-api-key` ヘッダで渡します。

**Q. generative-ai-go はまだ使えますか。**  
A. パッケージ自体は公開されたままなので `go get` は通りますが、サポートは2025年11月30日で終了しており、最終リリースは2025年5月のv0.20.1です。なおEOL日は当初の2025年8月31日から二度延長された経緯があり、タグ時点のREADMEを引用している記事は古い日付のままになっています。いずれにせよ新しいモデルや機能は反映されないため、新規実装で選ぶ理由はありません。`google.golang.org/genai` へ移行してください。

**Q. Goで指定するモデルIDはどれを選べばよいですか。**  
A. 迷うなら `gemini-2.5-flash` から始めるのが無難です。SDK公式サンプルの既定値であり、シャットダウン日も未告知です。最新世代が必要なら `gemini-3.6-flash` を指定します。`gemini-2.0-flash` 系はシャットダウン日の2026年6月1日を過ぎており、いつ停止されてもおかしくないため選ばないでください。

**Q. APIキーは GOOGLE\_API\_KEY と GEMINI\_API\_KEY のどちらを設定すべきですか。**  
A. どちらか一方だけを設定してください。両方が設定されている場合、SDKは警告ログを出したうえで `GOOGLE_API_KEY` を優先します。他のGoogle系APIと環境変数を共用している環境では、意図しないキーが使われて認証エラーになる原因になります。

**Q. goroutineで並列にリクエストしても問題ありませんか。**  
A. クライアントは並行利用できますが、レート制限がプロジェクト単位でかかるため同時実行数の上限は必ず設けてください。`errgroup.SetLimit` で上限を固定し、429と503はエクスポネンシャルバックオフで再試行する構成が基本です。

## 関連記事

- [Go 1.27の新機能・変更点まとめ｜最新バージョンの確認方法と移行ガイド](/tech/details/10416/)
- [Gemini 3とは？Google最新AIモデルの特徴・ラインアップ・料金と3.1への進化](/tech/details/10092/)
- [Gemini 3.1 Proとは｜料金・有料プラン(Plus/Pro/Ultra)・API単価とスペックを解説【2026年2月リリース】](/tech/details/11077/)
- [コンテキストウィンドウとは？トークン上限の数え方と有効長・溢れ対策を実装者向けに解説](/tech/details/16061/)
- [503エラーとは？原因の切り分けと復旧・再発防止をサーバー実装目線で解説【2026年版】](/tech/details/13172/)

---

出典: [GoでGemini APIを呼び出す実装手順｜SDKとエンドポイントURL【2026年8月版】](<https://www.issoh.co.jp/tech/details/2760/>)（株式会社一創）
