AI-модели в Go через AI Gateway
официальный SDK openai-go
AI Gateway совместим с официальным SDK openai-go: весь код — как в документации OpenAI, задаются только базовый URL и ключ через option. Один клиент даёт доступ ко всем моделям каталога — Claude, GPT, Gemini, DeepSeek — сменой параметра модели. Примеры ниже — под актуальный мажор SDK (модуль github.com/openai/openai-go/v3, требует Go 1.25+): в нём необязательные поля задаются напрямую или хелперами вроде openai.String, а обёртка openai.F(...) из ранних версий удалена.
Установка
go get github.com/openai/openai-go/v3Первый запрос
package mainimport ("context""fmt""github.com/openai/openai-go/v3""github.com/openai/openai-go/v3/option")func main() {client := openai.NewClient(option.WithBaseURL("https://ai-gatewey.ru/v1"),option.WithAPIKey("sk-aigate-ваш_ключ"),)resp, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{Model: "deepseek/deepseek-v4-flash",Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("Привет!"),},})if err != nil {panic(err)}fmt.Println(resp.Choices[0].Message.Content)}os.Getenv("AIGATE_API_KEY")), а не в коде — так его не утащат из репозитория. option.WithAPIKey принимает любое строковое значение.Стриминг
Ответ частями через Server-Sent Events — метод NewStreaming возвращает поток ssestream, который перебирают в цикле по Next():
stream := client.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{Model: "deepseek/deepseek-v4-flash",Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("Расскажи о токенах"),},})defer stream.Close()for stream.Next() {chunk := stream.Current()if len(chunk.Choices) > 0 {fmt.Print(chunk.Choices[0].Delta.Content)}}if err := stream.Err(); err != nil {panic(err)}Function calling
Вызов инструментов работает прозрачно — выбирайте модель с поддержкой function calling (бейдж «инструменты» в каталоге). Инструмент собирается хелпером openai.ChatCompletionFunctionTool, а модель возвращает ToolCalls:
resp, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{Model: "anthropic/claude-sonnet-5.5",Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("Какая погода в Москве?"),},Tools: []openai.ChatCompletionToolUnionParam{openai.ChatCompletionFunctionTool(openai.FunctionDefinitionParam{Name: "get_weather",Description: openai.String("Погода в городе"),Parameters: openai.FunctionParameters{"type": "object","properties": map[string]any{"city": map[string]string{"type": "string"},},"required": []string{"city"},},}),},})if err != nil {panic(err)}fmt.Println(resp.Choices[0].Message.ToolCalls)Обработка ошибок
401— неверный или отозванный ключ: проверьте значение и что ключ активен в кабинете.402— нужна оплата: пуст баланс, исчерпана месячная квота, модель не входит в тариф, либо сработал лимит самого ключа (список моделей, потолок расхода, срок действия). Пополните баланс, смените тариф либо проверьте настройки ключа.429— превышен лимит запросов в минуту: снизьте темп и повторите с экспоненциальной паузой.5xx— сбой апстрима: шлюз сам повторяет запрос, резервные провайдеры модели подставляет апстрим, но свой retry с экспоненциальной паузой в проде не помешает.
import ("errors""github.com/openai/openai-go/v3")_, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{Model: "deepseek/deepseek-v4-flash",Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("Привет!"),},})var apiErr *openai.Errorif errors.As(err, &apiErr) {// apiErr.StatusCode == 402 → нужна оплата; 429 → лимит запросов в минутуfmt.Println(apiErr.StatusCode, apiErr.Message)}Какую модель выбрать
Частые вопросы
Какой SDK для Go выбрать?
Официальный github.com/openai/openai-go/v3 — он поддерживается OpenAI и совместим с AI Gateway через option.WithBaseURL. Сторонние клиенты вроде go-openai тоже работают, если умеют менять базовый URL.
Как задать таймаут и повторы?
Через option.WithRequestTimeout и option.WithMaxRetries при создании клиента, либо контекстом context.WithTimeout на конкретный запрос.
Можно ли переключать модели без нового клиента?
Да — клиент создаётся один раз, а модель задаётся в каждом запросе полем Model, поэтому один клиент работает со всеми моделями каталога.