Volver al blog

API y SDKGuía

Primera petición en Go con openai-go: base URL, clave, usage

Un programa Go completo que llama a un modelo de CheapTokens mediante openai-go e imprime la respuesta, finish_reason y el uso de tokens, con reintentos y un tiempo de espera.

Por CheapTokens TeamPublicado el 6 min de lectura

Portada: Primera petición en Go con el SDK openai-go, una terminal con go run y la respuesta, finish_reason y usage
En esta página
  1. Qué necesitas antes de empezar
  2. El programa completo
  3. Lee la respuesta, finish_reason y usage
  4. Reintentos y tiempos de espera: tres límites distintos
  5. Cuánto cuestan mil de estas llamadas
  6. Si no funciona

Ya tienes código Go que habla con una API al estilo OpenAI, o estás a punto de escribirlo. Para enviarlo a CheapTokens cambias dos opciones del cliente y una cadena, el id del modelo. El SDK sigue siendo el mismo: el paquete oficial openai-go, v3.

A continuación está el programa completo, luego qué hace cada línea, cómo leer la respuesta y los recuentos de tokens, y cómo evitar que una petición atascada cuelgue tu servicio. Versiones comprobadas con el README de openai-go el 3 de noviembre de 2026: la última etiqueta de esa página es v3.91.1, y necesita Go 1.26 o superior.

Qué necesitas antes de empezar#

  • Go 1.26 o superior. En Go 1.25 fija v3.74.0; en Go 1.22–1.24 fija v3.44.0 (el README dice que la línea antigua no recibe correcciones garantizadas).
  • Una clave de API de CheapTokens. Guárdala en una variable de entorno, no en el archivo fuente.
  • La dirección de la API: https://api.cheaptokens.dev/v1. Habla el formato OpenAI Chat Completions, así que openai-go funciona sin un wrapper. La documentación tiene la misma dirección y la página de la clave.
  • Un id de modelo. Usamos deepseek-ai/DeepSeek-V4-Flash-0731: 380K de contexto y hasta 32.768 tokens en una respuesta. Usa el id completo; la API no acepta el nombre corto de las tablas de precios.

Paso a paso

Configura el proyecto

Instala el SDK

En una carpeta vacía:

bash
go mod init example.com/first-request
go get -u 'github.com/openai/openai-go/[email protected]'

La ruta de importación es github.com/openai/openai-go/v3, el nombre del paquete es openai.

Pon la clave en el entorno

bash
export CHEAPTOKENS_API_KEY="paste-your-key-here"

En Windows PowerShell: $env:CHEAPTOKENS_API_KEY = "paste-your-key-here". El marcador de posición no es una clave real.

Crea main.go y ejecútalo

Pega el programa de la siguiente sección en main.go, luego ejecuta go run ..

El programa completo#

go
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/openai/openai-go/v3"
	"github.com/openai/openai-go/v3/option"
)

func main() {
	client := openai.NewClient(
		option.WithBaseURL("https://api.cheaptokens.dev/v1"),
		option.WithAPIKey(os.Getenv("CHEAPTOKENS_API_KEY")),
		option.WithMaxRetries(2),
		option.WithRequestTimeout(30*time.Second),
	)

	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
	defer cancel()

	resp, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
		Model: "deepseek-ai/DeepSeek-V4-Flash-0731",
		Messages: []openai.ChatCompletionMessageParamUnion{
			openai.UserMessage("Explain in two sentences what a token is."),
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	if len(resp.Choices) == 0 {
		log.Fatal("no choices in the response")
	}

	fmt.Println(resp.Choices[0].Message.Content)
	fmt.Println("finish_reason:", resp.Choices[0].FinishReason)
	fmt.Println("input tokens:", resp.Usage.PromptTokens)
	fmt.Println("output tokens:", resp.Usage.CompletionTokens)
	fmt.Println("total tokens:", resp.Usage.TotalTokens)
}
El recorrido de una petición: clave desde el entorno, cliente openai-go, chat completion, luego content, finish_reason y usage
Qué hace el programa, en orden

Las piezas que importan:

  • option.WithBaseURL(...) es la única línea que mueve el SDK de OpenAI a CheapTokens. Usa la dirección exactamente como en la documentación.
  • option.WithAPIKey(os.Getenv(...)) pasa la clave explícitamente. Sin ella, el cliente lee OPENAI_API_KEY, lo cual es útil cuando portas código existente: asigna esa variable a una clave de CheapTokens y el código no necesita cambiar la clave. Lo mismo ocurre con OPENAI_BASE_URL, pero un WithBaseURL explícito lo anula, así que no hay sorpresa si existen ambos.
  • Model es una cadena simple en el SDK (ChatModel es un alias de string), así que cualquier id de modelo funciona, no solo las constantes que muestra el README.
  • openai.UserMessage(...) es un turno de usuario. El ejemplo del README usa DeveloperMessage y una constante de GPT; aquí un mensaje de usuario y un id de cadena son suficientes.

Lee la respuesta, finish_reason y usage#

Los tres vienen de campos que el SDK ya analiza por ti:

  • resp.Choices[0].Message.Content es el texto (un string).
  • resp.Choices[0].FinishReason también es un string. stop significa que el modelo terminó por su cuenta; length significa que la respuesta alcanzó el límite de tokens y se cortó. Si ves length, lee por qué una respuesta se detiene a mitad de frase.
  • resp.Usage contiene PromptTokens (lo que enviaste), CompletionTokens (lo que escribió el modelo) y TotalTokens, todos int64.

La salida se verá así: la respuesta, luego finish_reason: con un valor, luego tres recuentos de tokens. Los números cambian en cada ejecución, así que regístralos. Son lo que pagas, y los tokens de salida son el lado más caro.

Pruébalo tú mismoPruébalo: ¿qué cambia si intercambias el modelo?Mostrar respuesta

Cambia la cadena Model a zai-org/GLM-5.3-Flash y ejecuta de nuevo. Nada más en el programa se mueve. El texto de la respuesta y los tres números de usage serán distintos, que es la forma más rápida de comparar dos modelos con tu propio prompt. GLM-5.3-Flash tiene 390K de contexto y hasta 8.192 tokens en una respuesta.

Reintentos y tiempos de espera: tres límites distintos#

Aquí es donde los servicios Go suelen sufrir: por defecto el SDK no tiene ningún tiempo de espera, así que una conexión atascada puede esperar para siempre. Tres ajustes lo solucionan, y funcionan en niveles distintos:

  • option.WithMaxRetries(2): el SDK reintenta errores de conexión, 408, 409, 429 y 5xx con una breve espera exponencial. Dos reintentos ya es el valor por defecto; 0 desactiva los reintentos. Puedes configurarlo en el cliente, o en una llamada concreta.
  • option.WithRequestTimeout(30*time.Second): el límite para un intento.
  • El plazo de context: el límite para toda la llamada, reintentos y esperas incluidos.

Así que con 2 reintentos puede haber hasta 3 intentos: 3 × 30 = 90 segundos de espera en el peor caso, más las breves pausas entre intentos. Un contexto de dos minutos lo cubre. Si quieres una regla estricta de respuesta en 20 segundos para un handler web, acorta el contexto, no solo el tiempo de espera por intento.

Valores por defecto comparados con los ajustes del programa: dos reintentos en ambos, sin tiempo de espera por defecto frente a un tiempo de espera de 30 segundos por intento
Valores por defecto frente al programa anterior

Para más contexto sobre cómo elegir estos números, la versión en Python del mismo consejo está en Tiempos de espera y reintentos del SDK de OpenAI para Python. La lógica se traslada a Go.

Cuánto cuestan mil de estas llamadas#

Digamos que ejecutas un pequeño servicio que hace 1.000 peticiones al día, cada una con unos 800 tokens de entrada y 300 de salida. En deepseek-ai/DeepSeek-V4-Flash-0731 ese día cuesta $0.042 (1.000 × 800 tokens de entrada, 1.000 × 300 tokens de salida). La tabla muestra la misma carga en nuestros modelos; contado en total, con entrada y salida juntas, es más barato que OpenRouter.

Modelo Por solicitud 1000 solicitudes OpenRouter, 1000 solicitudes
GLM-5.3-Flash $0.000028 $0.028 $0.0517
DeepSeek-V4-Flash $0.000042 $0.042 $0.098
MiniMax-M2.7 $0.000085 $0.085 $1.02

800 tokens de entrada y 300 tokens de salida por solicitud. Los precios por 1M de tokens son actuales y cambian junto con nuestras tarifas; la columna de OpenRouter muestra precios de referencia para la misma carga de trabajo.

Introduce tus propios números. Tu primera ejecución imprime los PromptTokens y CompletionTokens reales, así que no tienes que adivinar la media:

Calculadora de costos

Un día de un pequeño servicio Go

Tokens de entrada por solicitud: 800 · Tokens de salida por solicitud: 300 · Solicitudes por día: 1000

ModeloPor díaPor mes
GLM-5.3-Flash$0.028$0.84
DeepSeek-V4-Flash$0.042$1.26
MiniMax-M2.7$0.085$2.55

Los precios de la página de precios y la página de modelos están en vivo y usan un precio fijo por modelo, sin horas punta.

Si no funciona#

  • El error menciona 401: la clave está vacía o es incorrecta. os.Getenv devuelve una cadena vacía para una variable no definida, así que comprueba echo $CHEAPTOKENS_API_KEY en la misma terminal donde ejecutas go run ..
  • El error menciona 404 o un modelo desconocido: el id. Cópialo completo, con el prefijo deepseek-ai/. Puedes listar los ids en la llamada de listado de modelos.
  • go: module requires Go 1.26: tu toolchain es más antiguo. Fija una etiqueta del SDK más antigua como se muestra arriba.
  • La llamada se cuelga y luego falla: eso es el tiempo de espera haciendo su trabajo. Comprueba primero la ruta de red, luego aumenta WithRequestTimeout si el modelo realmente necesita más tiempo para una respuesta larga.

Si la idea de base URL es nueva para ti, qué es base_url y cómo cambiarlo lo explica sin código.