El entorno de ejecución de Go

Cloud Functions es compatible con los siguientes entornos de ejecución de Go:

  • Go 1.11
  • Go 1.13

A fin de obtener instrucciones sobre cómo preparar tu máquina local para el desarrollo con Go, consulta Configura un entorno de desarrollo de Go.

Para comenzar con Go en Cloud Functions, consulta la guía de inicio rápido.

Selecciona el entorno de ejecución

Puedes seleccionar el entorno de ejecución de Go para tu función durante la implementación.

gcloud

Si usas la herramienta de línea de comandos de gcloud, puedes especificar el entorno de ejecución mediante el parámetro --runtime con el entorno de ejecución de Go que prefieras (los valores admitidos son go111 o go113). Por ejemplo:

gcloud functions deploy FUNCTION_NAME --runtime go113 FLAGS...

FLAGS... hace referencia a los argumentos que se pasaron durante la primera implementación de tu función. Para obtener más información sobre los argumentos obligatorios y los opcionales, consulta Implementa con la herramienta de gcloud.

Console

Si usas Cloud Console, puedes seleccionar el entorno de ejecución cuando creas y cuando implementas una función.

  1. En Cloud Console, ve a la página Descripción general de Cloud Functions.

    Ir a la página Descripción general de Cloud Functions

    Asegúrate de que el proyecto para el que habilitaste Cloud Functions esté seleccionado.

  2. Haz clic en Crear función.

  3. En Entorno de ejecución, selecciona el entorno de ejecución de Go que desees (por ejemplo, Go 1.13).

Entorno de ejecución

El entorno de ejecución incluye el tiempo de ejecución, el sistema operativo, los paquetes y una biblioteca que invoca tu función.

Los entornos de Go 1.11.6 y Go 1.13.8 usan un entorno de ejecución basado en Ubuntu 18.04. Consulta Entorno de ejecución de Cloud Functions para obtener más información.

Estructura del código fuente

A fin de que Cloud Functions encuentre la definición de tu función, cada entorno de ejecución tiene ciertos requisitos de estructura para el código fuente. Consulta Escribe funciones de Cloud Functions para obtener más información.

Especifica dependencias

Cloud Functions en Go debe proporcionar todas sus dependencias a través de los módulos de Go con un archivo go.mod o un directorio vendor. Para obtener más información, consulta Especifica dependencias en Go.

Inicialización única

Es posible que tus funciones necesiten realizar una inicialización única, como crear clientes de API y configurar el acceso a bases de datos. Hay distintas formas de hacerlo:

  • Usa una función func init() para inicializar los valores cuando se inicie una nueva instancia de tu función. Ten en cuenta que el código en la función func init() se ejecuta antes de que tu función reciba su primera solicitud.

  • Usa la función sync.Once.Do() para ejecutar código una vez por instancia de Cloud Functions. Hacer esto resulta útil en los casos en los que solo quieres inicializar a pedido y no cuando la instancia de la función se inicia primero. Por ejemplo, es posible que solo necesites inicializar un cliente de base de datos en ciertas circunstancias.

context.Context

El paquete context de Go define el tipo de Context, que lleva fechas límite, indicadores de cancelación y otros valores de alcance de la solicitud en todos los límites de la API y entre procesos.

Los clientes de la API que sobreviven a la invocación de una función dada deben inicializarse con un valor context.Context global, como el que creó la función context.Background(). Para optimizar el rendimiento, podrías inicializar un cliente en alcance global. Es posible que este cliente y su contexto se conserven durante el ciclo de vida de una instancia de función determinada.

Solo debes usar el contexto de invocación de función para objetos u operaciones que caen dentro del ciclo de vida de una invocación de función específica. El contexto de invocación podría cancelarse en cualquier punto después de que tu función termina de ejecutarse, lo que significa que cualquier cliente inicializado con este contexto podría cerrarse. Se puede acceder al contexto de invocación de la función a través de los argumentos de la función: por lo general, se usa r.Context() para las funciones de HTTP y ctx para las funciones en segundo plano.

Consulta el siguiente código para ver un ejemplo con un cliente de Pub/Sub:


// Package contexttip is an example of how to use Pub/Sub and context.Context in
// a Cloud Function.
package contexttip

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

	"cloud.google.com/go/pubsub"
)

// GOOGLE_CLOUD_PROJECT is a user-set environment variable.
var projectID = os.Getenv("GOOGLE_CLOUD_PROJECT")

// client is a global Pub/Sub client, initialized once per instance.
var client *pubsub.Client

func init() {
	// err is pre-declared to avoid shadowing client.
	var err error

	// client is initialized with context.Background() because it should
	// persist between function invocations.
	client, err = pubsub.NewClient(context.Background(), projectID)
	if err != nil {
		log.Fatalf("pubsub.NewClient: %v", err)
	}
}

type publishRequest struct {
	Topic   string `json:"topic"`
	Message string `json:"message"`
}

// PublishMessage publishes a message to Pub/Sub. PublishMessage only works
// with topics that already exist.
func PublishMessage(w http.ResponseWriter, r *http.Request) {
	// Parse the request body to get the topic name and message.
	p := publishRequest{}

	if err := json.NewDecoder(r.Body).Decode(&p); err != nil {
		log.Printf("json.NewDecoder: %v", err)
		http.Error(w, "Error parsing request", http.StatusBadRequest)
		return
	}

	if p.Topic == "" || p.Message == "" {
		s := "missing 'topic' or 'message' parameter"
		log.Println(s)
		http.Error(w, s, http.StatusBadRequest)
		return
	}

	m := &pubsub.Message{
		Data: []byte(p.Message),
	}
	// Publish and Get use r.Context() because they are only needed for this
	// function invocation. If this were a background function, they would use
	// the ctx passed as an argument.
	id, err := client.Topic(p.Topic).Publish(r.Context(), m).Get(r.Context())
	if err != nil {
		log.Printf("topic(%s).Publish.Get: %v", p.Topic, err)
		http.Error(w, "Error publishing message", http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "Message published: %v", id)
}