Go ランタイム

Cloud Functions は、次の Go ランタイムをサポートしています。

  • Go 1.11
  • Go 1.13

Go 開発用にローカルマシンを準備する方法については、Go 開発環境の設定をご覧ください。

Cloud Functions で Go の使用を開始するには、クイックスタートをご覧ください。

ランタイムの選択

デプロイ時に関数の Go ランタイムを選択できます。

gcloud

gcloud コマンドライン ツールを使用している場合は、選択した Go ランタイムで --runtime パラメータを使用して、ランタイムを指定できます(サポートされている値は go111 または go113 です)。例:

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

FLAGS... は関数の最初のデプロイ時に渡される引数です。必須の引数とオプションの引数については、gcloud ツールを使用したデプロイをご覧ください。

Console

Cloud Console を使用している場合は、関数を作成してデプロイするときにランタイムを選択できます。

  1. Cloud Console で、Cloud Functions の概要ページに移動します。

    Cloud Functions の概要ページに移動

    Cloud Functions を有効にしたプロジェクトが選択されていることを確認します。

  2. [関数を作成] をクリックします。

  3. [ランタイム] で、選択した Go ランタイム(たとえば、Go 1.13)を選択します。

実行環境

実行環境には、ランタイム、オペレーティング システム、パッケージ、関数を呼び出すライブラリが含まれます。

Go 1.11.6 と Go 1.13.8 ランタイムでは、Ubuntu 18.04 に基づく実行環境を使用します。詳しくは、Cloud Functions の実行環境をご覧ください。

ソースコードの構造

Cloud Functions で関数の定義を見つけられるよう、ランタイムごとに、ソースコードの構造に対する特定の要件があります。詳しくは、Cloud Functions の作成をご覧ください。

依存関係の指定

Go の Cloud Functions では、go.mod ファイルを含む Go モジュール、または vendor ディレクトリのいずれかによって、すべての依存関係を指定する必要があります。詳しくは、Go での依存関係の指定をご覧ください。

1 回限りの初期化

関数によっては、API クライアントの作成やデータベース アクセスの構成など、1 回限りの初期化が必要になる場合があります。これを行うには、次のような方法があります。

  • func init() 関数を使用して、関数の新しいインスタンスが起動したときに値を初期化します。func init() 関数内のコードは、関数が最初のリクエストを受信する前に実行されることに注意してください。

  • sync.Once.Do() 関数を使用して、Cloud Functions の各インスタンスで 1 回だけコードを実行します。これは、関数のインスタンスが最初に起動したときではなく、リクエストに応じた初期化を行う場合に役立ちます。たとえば、特定の状況において、データベース クライアントのみを初期化したい場合があります。

context.Context

Go の context パッケージContext 型を定義します。この型は、API の境界を越えてプロセス間で期限、キャンセル シグナル、その他のリクエスト スコープ値を保持します。

特定の関数呼び出しより長く存続する API クライアントは、グローバルな context.Context 値で初期化する必要があります(たとえば、context.Background() 関数で作成された値)。パフォーマンスを最適化するため、グローバル スコープでクライアントを初期化するという方法があります。このクライアントとそのコンテキストは、特定の関数のインスタンス存続期間にわたって持続する可能性があります。

関数呼び出しコンテキストは、特定の関数呼び出しの存続期間内に限定して存在するオブジェクトまたはオペレーションに対してのみ使用してください。 呼び出しコンテキストは、関数の実行が終了した後はいつでも取り消される可能性があります。つまり、このコンテキストを使用して初期化されたクライアントは閉じられる可能性があります。関数呼び出しコンテキストには、関数の引数を通じてアクセスできます。通常、HTTP 関数の場合は r.Context()、バックグラウンド関数の場合は ctx です。

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)
}