Go Cloud Development Kit (Go CDK)を使う理由

Go

2024-09-10

#目次

#はじめに

今回は、Go Cloud Development Kit (以後、Go CDK)という便利なライブラリを紹介します。
前回、WireというDIライブラリを記事で紹介しましたが、Wireは、実はGo CDKの一部です。
Go CDKの使い方などのコードは、この記事では扱いませんので、公式ドキュメントを参照してください。

#Go CDKとは

The Go Cloud Development Kit (Go CDK) is an open source project building libraries and tools to improve the experience of developing for the cloud with Go.
Go CDK provides commonly used, vendor-neutral generic APIs that you can deploy across cloud providers. The idea is to support hybrid cloud deployments while combining on-prem (local) and cloud tools.

出典:https://gocloud.dev/
参考:https://go.dev/blog/go-cloud

Go CDKを使うと、クラウドプロバイダに依存しないコードを書くことができます。
例えば、blobというインターフェースを使うことで、ストレージサービス(ex. Google Cloud Storage, S3, Azure Blob Storage, Local Storage)へのアクセスをローカル開発環境と各種クラウド環境で同じコードを使うことができます。
これらにより、マルチクラウドアプリケーション、ハイブリッドクラウドアプリケーションを開発することが容易になります。
blob以外にも、docstore,pubsub,runtimevar,secretsなどの各クラウドプロバイダが一般的に提供しているサービスのインターフェースが提供されています。

#なぜGo CDKを使うのか

いくつかのGo言語のプロジェクトに関わってきた中で、課題は以下の通りです。

  1. 複数のクラウドプロバイダのAPIを使うためのコードを書く必要がある
  2. ローカル開発環境とクラウド環境で異なるコードを書く必要がある

1つ目の課題は、いくつかのプロジェクトを関わる中でAWSを使うプロジェクトもあれば、Google Cloudを使うプロジェクトもあり、クラウドプロバイダに依存しないコードを書くことが難しいと感じていました。具体的には、aws-sdk-goのS3を使うコードと、google.golang.org/api/storage/v1を使うコードを書く必要があります。ストレージを扱うという点で同じですが、APIが異なるため、コードを書くたびにAPIの違いを意識しながらコードを書く必要があります。
Go CDKを使うことで、クラウドプロバイダに依存しないコードを書くことができるため、この課題を解決できます。

2つ目の課題は、ローカル開発環境とクラウド環境で異なるコードを書く必要があるということです。私のローカル開発環境の要件は、エンドツーエンドのテストができることです。そのため、ローカル開発環境でクラウドプロバイダのAPIを使うためのコードを書く必要があります。Go CDKを使うことで、ローカル開発環境では、たとえば、ローカルファイルシステムを使い、クラウド環境では、Google Cloud Storageを使うコードを書くことができます。これらは、抽象化されているため、コンポーネントの生成時に、どのストレージサービスを使うかを指定するだけで、ローカル開発環境とクラウド環境で異なるコードを書く必要がなくなります。

#DIするためのインターフェースを定義する

Go CDKでは、インターフェースは提供されていませんので、ユニットテストをするためには、インターフェースを定義すると良いでしょう。
例えば、blobのインターフェースを定義すると以下のようになります。

package blob

import (
	"context"

	"gocloud.dev/blob"
)

//go:generate mockgen -destination=${GOPACKAGE}mocks/${GOFILE} -package=${GOPACKAGE}mocks -source=$GOFILE

type Attributes = blob.Attributes
type CopyOptions = blob.CopyOptions
type ListOptions = blob.ListOptions
type ReaderOptions = blob.ReaderOptions
type SignedURLOptions = blob.SignedURLOptions
type WriterOptions = blob.WriterOptions
type ListIterator = blob.ListIterator
type ListObject = blob.ListObject
type Reader = blob.Reader
type Writer = blob.Writer

var _ Bucket = (*blob.Bucket)(nil)

type Bucket interface {
	As(i interface{}) bool
	Attributes(ctx context.Context, key string) (_ *Attributes, err error)
	Close() error
	Copy(ctx context.Context, dstKey, srcKey string, opts *CopyOptions) (err error)
	Delete(ctx context.Context, key string) (err error)
	ErrorAs(err error, i interface{}) bool
	Exists(ctx context.Context, key string) (bool, error)
	IsAccessible(ctx context.Context) (bool, error)
	List(opts *ListOptions) *ListIterator
	ListPage(ctx context.Context, pageToken []byte, pageSize int, opts *ListOptions) (retval []*ListObject, nextPageToken []byte, err error)
	NewRangeReader(ctx context.Context, key string, offset, length int64, opts *ReaderOptions) (_ *Reader, err error)
	NewReader(ctx context.Context, key string, opts *ReaderOptions) (*Reader, error)
	NewWriter(ctx context.Context, key string, opts *WriterOptions) (_ *Writer, err error)
	ReadAll(ctx context.Context, key string) (_ []byte, err error)
	SignedURL(ctx context.Context, key string, opts *SignedURLOptions) (string, error)
	WriteAll(ctx context.Context, key string, p []byte, opts *WriterOptions) (err error)
}

Go CDKのblobは、Bucket構造体を提供しますので、その構造体の関数をインターフェースに定義するだけです。
このインターフェースからmockgenを使ってモックを生成することで、ユニットテストを書くことができます。
pubsubdocstoreなどのインターフェースも同様に定義することができます。

#注意点

Go CDKでは計装については、OpenCensusが採用されています。しかし、OpenCensusは、OpenTelemetryに移行されていますので、計装を実装する場合は、OpenTelemetryを使うことをおすすめします。
こちらのissueではOpenTelemetryに移行することが議論されていますが、まだ移行されていません。OpenTelemetryで計装を実装する場合は、例えば、自分でBucketインターフェースをWrapして、計装を実装すると良いでしょう。すこし手間がかかりますが。

#まとめ

今回は、Go Cloud Development Kit (Go CDK)について紹介しました。
もし複数のプロダクトで異なるクラウドプロバイダのAPIを使うコードを書いている場合は、Go CDKを使うことで、クラウドプロバイダに依存しないコードを書くことができます。
Go CDKは、Go言語でクラウドアプリケーションを開発する際に便利なライブラリですので、ぜひ使ってみてください。
次回は、Goで環境変数の取り扱いをするライブラリ(godotenv, envconfig)を紹介したいと思います。