Google Gemini API API in Go

Google Gemini API API in Go

This guide shows you how to integrate the Google Gemini API into your Go application. Google’s multimodal AI model for text, image, video, and audio understanding.

Prerequisites

  • Go installed on your system
  • An Google Gemini API API key (sign up at https://ai.google.dev)
  • Basic familiarity with HTTP APIs

Installation

go mod init myapp
go get github.com/go-resty/resty/v2

Basic Usage

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    apiKey := os.Getenv("API_KEY")
    if apiKey == "" {
        apiKey = "YOUR_API_KEY"
    }
    baseURL := "https://generativelanguage.googleapis.com"

    req, _ := http.NewRequest("GET", baseURL+"/v1/resources", nil)
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println("Status:", resp.Status)
    fmt.Println(string(body))
}

Error Handling

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func callAPIWithRetry(url, apiKey string, maxRetries int) ([]byte, error) {
    var lastErr error
    for attempt := 0; attempt < maxRetries; attempt++ {
        req, _ := http.NewRequest("GET", url, nil)
        req.Header.Set("Authorization", "Bearer "+apiKey)

        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            lastErr = err
            time.Sleep(time.Duration(1<<attempt) * time.Second)
            continue
        }

        if resp.StatusCode == 429 {
            retryAfter := resp.Header.Get("Retry-After")
            fmt.Println("Rate limited. Retry-After:", retryAfter)
            resp.Body.Close()
            time.Sleep(60 * time.Second)
            continue
        }

        if resp.StatusCode >= 400 {
            body, _ := io.ReadAll(resp.Body)
            resp.Body.Close()
            lastErr = fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
            time.Sleep(time.Duration(1<<attempt) * time.Second)
            continue
        }

        body, err := io.ReadAll(resp.Body)
        resp.Body.Close()
        return body, err
    }
    return nil, lastErr
}

func main() {
    apiKey := os.Getenv("API_KEY")
    body, err := callAPIWithRetry("https://generativelanguage.googleapis.com/v1/resources", apiKey, 3)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(body))
}

Advanced Usage

package main

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

type GeminiClient struct {
    APIKey  string
    BaseURL string
    HTTP    *http.Client
}

func NewClient(apiKey, baseURL string) *GeminiClient {
    return &GeminiClient{
        APIKey:  apiKey,
        BaseURL: baseURL,
        HTTP:    &http.Client{Timeout: 30 * time.Second},
    }
}

func (c *GeminiClient) do(method, path string, body interface{}) ([]byte, error) {
    var reqBody io.Reader
    if body != nil {
        jsonData, _ := json.Marshal(body)
        reqBody = bytes.NewBuffer(jsonData)
    }
    req, _ := http.NewRequest(method, c.BaseURL+path, reqBody)
    req.Header.Set("Authorization", "Bearer "+c.APIKey)
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.HTTP.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    return io.ReadAll(resp.Body)
}

func (c *GeminiClient) ListResources() ([]byte, error) {
    return c.do("GET", "/v1/resources", nil)
}

func (c *GeminiClient) CreateResource(data map[string]interface{}) ([]byte, error) {
    return c.do("POST", "/v1/resources", data)
}

func main() {
    client := NewClient(os.Getenv("API_KEY"), "https://generativelanguage.googleapis.com")
    resources, err := client.ListResources()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(resources))
}

Best Practices

  • Store your API key in an environment variable, never in source code
  • Implement retry logic with exponential backoff for 429 and 5xx errors
  • Set reasonable timeouts (10-30 seconds) for all API calls
  • Log request IDs from response headers for debugging
  • Cache responses where appropriate to reduce API calls

Other languages