v2 AWS SDK for Go への移行 - AWS SDK for Go v2

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

v2 AWS SDK for Go への移行

Go の最小バージョン要件

には、Go 1.23 の最小バージョン AWS SDK for Go が必要です。Go の最新バージョンは「Downloads」ページからダウンロードできます。Go の各バージョンのリリース内容およびアップグレードの詳細については、「Release History」を参照してください。

モジュール化

AWS SDK for Go は、Go 1.13 のデフォルト開発モードになった Go モジュールを利用するように更新されました。SDK が提供する多くのパッケージはモジュール化され、それぞれ個別にバージョン管理およびリリースされています。この変更により、アプリケーションの依存関係モデリングが向上し、SDK が Go モジュールのバージョニング戦略に沿って新機能を提供できるようになります。

SDK が提供する主な Go モジュールのリストを次に示します。

モジュール 説明
github.com/aws/aws-sdk-go-v2 SDK コア
github.com/aws/aws-sdk-go-v2/config 共有設定のロード
github.com/aws/aws-sdk-go-v2/credentials AWS 認証情報プロバイダー
github.com/aws/aws-sdk-go-v2/feature/ec2/imds Amazon EC2 インスタンスメタデータのサービスクライアント

SDK のサービスクライアントおよび高レベルユーティリティモジュールは、次のインポートパス下にネストされています。

インポートルート 説明
github.com/aws/aws-sdk-go-v2/service/ サービスクライアントモジュール
github.com/aws/aws-sdk-go-v2/feature/ Amazon S3 Transfer Manager などのサービス用の高レベルユーティリティ

設定のロード

session パッケージとその関連機能は、config パッケージによって提供される簡素化された設定システムに置き換えられました。config パッケージは個別の Go モジュールであり、go get を使用してアプリケーションの依存関係に含めることができます。

go get github.com/aws/aws-sdk-go-v2/config

session.Newsession.NewSessionNewSessionWithOptions、および session.Mustconfig.LoadDefaultConfig に移行する必要があります。

config パッケージには、共有設定のロードをプログラムでオーバーライドするためのヘルパー関数がいくつか用意されています。これらの関数名は、With の後に、オーバーライドするオプション名が続く形式になっています。session パッケージの使用方法をどのように移行するかについていくつか例を見てみましょう。

共有設定のロードの詳細については、「SDK を設定」を参照してください。

NewSession から LoadDefaultConfig への移行

次の例では、追加の引数を指定せずに session.NewSession を使用していたコードを config.LoadDefaultConfig に移行する方法を示しています。

// V1 using NewSession import "github.com/aws/aws-sdk-go/aws/session" // ... sess, err := session.NewSession() if err != nil { // handle error }
// V2 using LoadDefaultConfig import "context" import "github.com/aws/aws-sdk-go-v2/config" // ... cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { // handle error }

aws.Config オプションを使用した NewSession からの移行

この例では、設定のロード中にオーバーライドされた aws.Config 値をどのように移行するかを示しています。config.With* に 1 つ以上の config.LoadDefaultConfig ヘルパー関数を指定することで、ロードされた設定値をオーバーライドできます。この例では、 AWS リージョンは config.WithRegion ヘルパー関数us-west-2を使用して に上書きされます。

// V1 import "github.com/aws/aws-sdk-go/aws" import "github.com/aws/aws-sdk-go/aws/session" // ... sess, err := session.NewSession(aws.Config{ Region: aws.String("us-west-2") }) if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/config" // ... cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-west-2"), ) if err != nil { // handle error }

NewSessionWithOptions からの移行

この例では、設定のロード中にオーバーライドされた値をどのように移行するかを示しています。config.LoadDefaultConfig に 0 個以上の config.With* ヘルパー関数を指定することで、ロードされた設定値をオーバーライドできます。この例では、 AWS SDK 共有設定をロードするときに使用するターゲットプロファイルを上書きする方法を示します。

// V1 import "github.com/aws/aws-sdk-go/aws" import "github.com/aws/aws-sdk-go/aws/session" // ... sess, err := session.NewSessionWithOptions(aws.Config{ Profile: "my-application-profile" }) if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/config" // ... cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithSharedConfigProfile("my-application-profile"), ) if err != nil { // handle error }

モック化と *iface

*iface パッケージおよびその中に含まれるインターフェイス (例: s3iface.S3API) は削除されました。これらのインターフェイス定義は、サービスに新しいオペレーションが追加されるたびに壊れるため、安定していません。

*iface の使用は、利用するサービスオペレーションに応じて、呼び出し元で定義したスコープ付きのインターフェイスに置き換える必要があります。

// V1 import "io" import "github.com/aws/aws-sdk-go/service/s3" import "github.com/aws/aws-sdk-go/service/s3/s3iface" func GetObjectBytes(client s3iface.S3API, bucket, key string) ([]byte, error) { object, err := client.GetObject(&s3.GetObjectInput{ Bucket: &bucket, Key: &key, }) if err != nil { return nil, err } defer object.Body.Close() return io.ReadAll(object.Body) }
// V2 import "context" import "io" import "github.com/aws/aws-sdk-go-v2/service/s3" type GetObjectAPIClient interface { GetObject(context.Context, *s3.GetObjectInput, ...func(*s3.Options)) (*s3.GetObjectOutput, error) } func GetObjectBytes(ctx context.Context, client GetObjectAPIClient, bucket, key string) ([]byte, error) { object, err := client.GetObject(ctx, &s3.GetObjectInput{ Bucket: &bucket, Key: &key, }) if err != nil { return nil, err } defer object.Body.Close() return io.ReadAll(object.Body) }

詳細については、「AWS SDK for Go v2 を使用したユニットテスト」を参照してください。

認証情報と認証情報プロバイダー

aws/credentials パッケージおよび関連する認証情報プロバイダーは credentials パッケージの場所に移動されました。credentials パッケージは Go モジュールであり、go get を使用して取得します。

go get github.com/aws/aws-sdk-go-v2/credentials

AWS SDK for Go v2 リリースでは AWS 、認証情報プロバイダーが更新され、認証情報を取得 AWS するための一貫したインターフェイスが提供されます。各プロバイダーは aws.CredentialsProvider インターフェイスを実装します。これは、v1 credentials(aws.Credentials, error).Value タイプに類似した . aws.Credentials AWS SDK for Go を返すRetrieveメソッドを定義します。

認証情報のキャッシュを行うには、aws.CredentialsProvider オブジェクトを aws.CredentialsCache でラップする必要があります。NewCredentialsCache を使用して aws.CredentialsCache オブジェクトを作成します。デフォルトでは、config.LoadDefaultConfig によって設定された認証情報は aws.CredentialsCache でラップされます。

次の表は、認証情報プロバイダーの場所を AWS AWS SDK for Go v1 から v2 に変更したものです。

Name V1 のインポート V2 のインポート
Amazon EC2 IAM ロールの認証情報 github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds
エンドポイント認証情報 github.com/aws/aws-sdk-go/aws/credentials/endpointcreds github.com/aws/aws-sdk-go-v2/credentials/endpointcreds
プロセス認証情報 github.com/aws/aws-sdk-go/aws/credentials/processcreds github.com/aws/aws-sdk-go-v2/credentials/processcreds
AWS Security Token Service github.com/aws/aws-sdk-go/aws/credentials/stscreds github.com/aws/aws-sdk-go-v2/credentials/stscreds

静的な認証情報

credentials.NewStaticCredentials を用いて静的認証情報をプログラムで作成するアプリケーションは、Credentials.NewStaticCredentialsProvider を使用する必要があります。

// V1 import "github.com/aws/aws-sdk-go/aws/credentials" // ... appCreds := credentials.NewStaticCredentials(accessKey, secretKey, sessionToken) value, err := appCreds.Get() if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/aws" import "github.com/aws/aws-sdk-go-v2/credentials" // ... appCreds := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(accessKey, secretKey, sessionToken)) value, err := appCreds.Retrieve(context.TODO()) if err != nil { // handle error }

Amazon EC2 IAM ロールの認証情報

NewCredentials および NewCredentialsWithClient の使用は New の使用に移行する必要があります。

ec2rolecreds パッケージの ec2rolecreds.New は、ec2rolecreds.Options の関数型オプションを入力として受け取ります。これにより、使用する特定の Amazon EC2 インスタンスメタデータサービスクライアントをオーバーライドしたり、認証情報の有効期限をオーバーライドしたりできます。

// V1 import "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" // ... appCreds := ec2rolecreds.NewCredentials(sess) value, err := appCreds.Get() if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/aws" import "github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds" // ... // New returns an object of a type that satisfies the aws.CredentialProvider interface appCreds := aws.NewCredentialsCache(ec2rolecreds.New()) value, err := appCreds.Retrieve(context.TODO()) if err != nil { // handle error }

エンドポイント認証情報

NewCredentialsClient および NewProviderClient の使用は New の使用に移行する必要があります。

endpointcreds パッケージの New 関数は、認証情報を取得する HTTP または HTTPS エンドポイントの URL を含む文字列引数と、endpointcreds.Options の関数型オプションを受け取って、認証情報プロバイダーの変更、特定の設定のオーバーライドができます。

プロセス認証情報

NewCredentialsNewCredentialsCommandNewCredentialsTimeout の使用は NewProvider または NewProviderCommand の使用に移行する必要があります。

processcreds パッケージの NewProvider 関数は、ホスト環境のシェルで実行するコマンドの文字列引数と、Options の関数型オプションを受け取って、認証情報プロバイダーの変更、特定の設定のオーバーライドができます。

NewProviderCommand は、より複雑なプロセスコマンド (1 つ以上のコマンドライン引数を取るものや、特定の実行環境要件があるものなど) を定義する NewCommandBuilder インターフェイスの実装を受け取ります。DefaultNewCommandBuilder はこのインターフェイスを実装しており、複数のコマンドライン引数を必要とするプロセスのコマンドビルダーを定義します。

// V1 import "github.com/aws/aws-sdk-go/aws/credentials/processcreds" // ... appCreds := processcreds.NewCredentials("/path/to/command") value, err := appCreds.Get() if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/aws" import "github.com/aws/aws-sdk-go-v2/credentials/processcreds" // ... appCreds := aws.NewCredentialsCache(processcreds.NewProvider("/path/to/command")) value, err := appCreds.Retrieve(context.TODO()) if err != nil { // handle error }

AWS Security Token Service 認証情報

AssumeRole

NewCredentials および NewCredentialsWithClient の使用は NewAssumeRoleProvider の使用に移行する必要があります。

stscreds パッケージの NewAssumeRoleProvider関数は、sts.Client、および指定された の設定済み認証情報から引き受ける AWS Identity and Access Management ロール ARN を使用して呼びsts.Client出す必要があります。AssumeRoleOptions の関数型オプションを指定して、プロバイダーの他のオプション設定を変更することもできます。

// V1 import "github.com/aws/aws-sdk-go/aws/credentials/stscreds" // ... appCreds := stscreds.NewCredentials(sess, "arn:aws:iam::123456789012:role/demo") value, err := appCreds.Get() if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/credentials/stscreds" import "github.com/aws/aws-sdk-go-v2/service/sts" // ... client := sts.NewFromConfig(cfg) appCreds := stscreds.NewAssumeRoleProvider(client, "arn:aws:iam::123456789012:role/demo") value, err := appCreds.Retrieve(context.TODO()) if err != nil { // handle error }

AssumeRoleWithWebIdentity

NewWebIdentityCredentialsNewWebIdentityRoleProviderNewWebIdentityRoleProviderWithToken の使用は NewWebIdentityRoleProvider の使用に移行する必要があります。

stscreds パッケージの NewWebIdentityRoleProvider関数は、sts.Client、指定された sts.Clientの設定済み認証情報を使用して引き受ける AWS Identity and Access Management ロール ARN、および OAuth 2.0 または OpenID Connect ID トークンを提供するための IdentityTokenRetriever の実装を使用して呼び出す必要があります。IdentityTokenFile は、アプリケーションのホストファイルシステム上のファイルからウェブ ID トークンを提供するために使用できる IdentityTokenRetriever です。WebIdentityRoleOptions の関数型オプションを指定して、プロバイダーの他のオプション設定を変更することもできます。

// V1 import "github.com/aws/aws-sdk-go/aws/credentials/stscreds" // ... appCreds := stscreds.NewWebIdentityRoleProvider(sess, "arn:aws:iam::123456789012:role/demo", "sessionName", "/path/to/token") value, err := appCreds.Get() if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/aws" import "github.com/aws/aws-sdk-go-v2/credentials/stscreds" import "github.com/aws/aws-sdk-go-v2/service/sts" // ... client := sts.NewFromConfig(cfg) appCreds := aws.NewCredentialsCache(stscreds.NewWebIdentityRoleProvider( client, "arn:aws:iam::123456789012:role/demo", stscreds.IdentityTokenFile("/path/to/file"), func(o *stscreds.WebIdentityRoleOptions) { o.RoleSessionName = "sessionName" })) value, err := appCreds.Retrieve(context.TODO()) if err != nil { // handle error }

サービスクライアント

AWS SDK for Go は、github.com/aws/aws-sdk-go-v2/serviceインポートパスの下にネストされたサービスクライアントモジュールを提供します。各サービスクライアントは、各サービスの一意の ID を使用した Go パッケージに含まれています。次の表では、 AWS SDK for Goにおけるサービスインポートパスの例をいくつか示しています。

サービス名 V1 インポートパス V2 インポートパス
Amazon S3 github.com/aws/aws-sdk-go/service/s3 github.com/aws/aws-sdk-go-v2/service/s3
Amazon DynamoDB github.com/aws/aws-sdk-go/service/dynamodb github.com/aws/aws-sdk-go-v2/service/dynamodb
Amazon CloudWatch Logs github.com/aws/aws-sdk-go/service/cloudwatchlogs github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs

各サービスクライアントパッケージは、個別にバージョニングされた Go モジュールです。サービスクライアントをアプリケーションの依存関係として追加するには、go get コマンドでサービスのインポートパスを指定します。例えば、Amazon S3 クライアントを依存関係に追加するには、次のようにします。

go get github.com/aws/aws-sdk-go-v2/service/s3

クライアントの作成

クライアントのパッケージの Newまたは コンNewFromConfigストラクタ関数 AWS SDK for Go を使用して、 でクライアントを構築できます。 AWS SDK for Go v1 から移行する場合は、 NewFromConfigバリアントを使用することをお勧めします。これにより、 の値を使用して新しいサービスクライアントが返されますaws.Configaws.Config の値は、config.LoadDefaultConfig を使用して SDK の共有設定をロードするときに作成されます。サービスクライアントの作成の詳細については、「AWS SDK for Go v2 を用いた AWS サービスを使用する」を参照してください。

例 1

// V1 import "github.com/aws/aws-sdk-go/aws/session" import "github.com/aws/aws-sdk-go/service/s3" // ... sess, err := session.NewSession() if err != nil { // handle error } client := s3.New(sess)
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/config" import "github.com/aws/aws-sdk-go-v2/service/s3" // ... cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { // handle error } client := s3.NewFromConfig(cfg)

例 2: クライアント設定のオーバーライド

// V1 import "github.com/aws/aws-sdk-go/aws" import "github.com/aws/aws-sdk-go/aws/session" import "github.com/aws/aws-sdk-go/service/s3" // ... sess, err := session.NewSession() if err != nil { // handle error } client := s3.New(sess, &aws.Config{ Region: aws.String("us-west-2"), })
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/config" import "github.com/aws/aws-sdk-go-v2/service/s3" // ... cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { // handle error } client := s3.NewFromConfig(cfg, func(o *s3.Options) { o.Region = "us-west-2" })

エンドポイント

endpoints パッケージは AWS SDK for Goに含まれなくなりました。各サービスクライアントは、クライアントパッケージに必要な AWS エンドポイントメタデータを埋め込むようになりました。これにより、アプリケーションで使用されていないサービスのエンドポイントメタデータが含まれなくなるため、コンパイルされたアプリケーションの全体的なバイナリサイズが削減されます。

さらに、各サービスはエンドポイント解決のための独自のインターフェイスを EndpointResolverV2 で公開するようになりました。各 API はサービスの EndpointParameters に固有のパラメータ群を受け取り、これらの値はオペレーション呼び出し時に SDK がさまざまな場所から取得します。

デフォルトでは、サービスクライアントは設定された AWS リージョンを使用して、ターゲットリージョンのサービスエンドポイントを解決します。アプリケーションでカスタムエンドポイントが必要な場合は、aws.Config 構造体の EndpointResolverV2 フィールドにカスタム動作を指定できます。アプリケーションでカスタムの endpoints.Resolver を実装している場合は、サービスごとの新しいインターフェイスに適合するように移行する必要があります。

エンドポイント、およびカスタムリゾルバーの実装の詳細については、「クライアントエンドポイントを設定する」を参照してください。

認証

AWS SDK for Go は、より高度な認証動作をサポートしているため、codecatalyst や S3 Express One Zone などの新しい AWS サービス機能を使用できます。さらに、この動作はクライアントごとにカスタマイズできます。

API オペレーションの呼び出し

サービスクライアントのオペレーションメソッドの数は大幅に削減されました。<OperationName>Request<OperationName>WithContext、および <OperationName> メソッドはすべて 1 つのオペレーションメソッド <OperationName> に統合されました。

次の例は、Amazon S3 PutObject オペレーションへの呼び出しを AWS SDK for Go v1 から v2 に移行する方法を示しています。

// V1 import "context" import "github.com/aws/aws-sdk-go/service/s3" // ... client := s3.New(sess) // Pattern 1 output, err := client.PutObject(&s3.PutObjectInput{ // input parameters }) // Pattern 2 output, err := client.PutObjectWithContext(context.TODO(), &s3.PutObjectInput{ // input parameters }) // Pattern 3 req, output := client.PutObjectRequest(context.TODO(), &s3.PutObjectInput{ // input parameters }) err := req.Send()
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/service/s3" // ... client := s3.NewFromConfig(cfg) output, err := client.PutObject(context.TODO(), &s3.PutObjectInput{ // input parameters })

サービスデータ型

オペレーションのトップレベルの入力および出力型は、サービスクライアントパッケージにあります。特定のオペレーションの入力および出力型は、<OperationName>Input および <OperationName>Output というパターンに従います。ここで、OperationName は呼び出そうとしているオペレーションの名前です。例えば、Amazon S3 の PutObject オペレーションの入力および出力型はそれぞれ PutObjectInput および PutObjectOutput です。

入力および出力型以外のすべてのサービスデータ型は、サービスクライアントパッケージのインポートパス階層下にある types パッケージに移行されました。例えば、s3.AccessControlPolicy 型は現在、types.AccessControlPolicy にあります。

列挙値

SDK では、すべての API の列挙型フィールドに対して、型付きで扱えるようになりました。サービス API リファレンスドキュメントからコピーした文字列リテラル値を使用する代わりに、サービスクライアントの types パッケージにある具象型を使用できます。例えば、Amazon S3 の PutObjectInput オペレーションに対して、オブジェクトに適用する ACL を指定できます。 AWS SDK for Go v1 では、このパラメータは *string型でした。 AWS SDK for Goでは、このパラメータは types.ObjectCannedACL 型になりました。types パッケージには、このフィールドに指定できる有効な列挙値に対応する定数が自動生成されています。例えば、types.ObjectCannedACLPrivate は「private」という既定の ACL 値に対応する定数です。この値を使用すれば、アプリケーション内で文字列定数を管理する必要がなくなります。

ポインタパラメータ

AWS SDK for Go v1 では、すべての入力パラメータに対してサービスオペレーションに渡されるポインタリファレンスが必要でした。 AWS SDK for Go v2 では、入力値をポインタとして渡す必要がなくなるため、ほとんどの サービスのエクスペリエンスが簡素化されました。この変更により、多くのサービスクライアントオペレーションで uint8uint16uint32int8int16int32float32float64bool の各型に対するポインタ参照を渡す必要がなくなりました。同様に、スライスとマップの要素型も、要素をポインタ参照として渡す必要があるかどうかに応じて更新されました。

aws パッケージには、Go の組み込み型に対応するポインタを生成するためのヘルパー関数が用意されています。これらのヘルパーを使用することで、これらの型のポインタ型の取り扱いがより簡単になります。同様に、これらの型に対応するポインタの参照外しを安全に行うためのヘルパーメソッドも用意されています。例えば、aws.String 関数は string*string の変換を行います。逆に、aws.ToString*stringstring の変換を行います。アプリケーションを AWS SDK for Go v1 から v2 にアップグレードする際は、ポインタ型から非ポインタ型への変換に使用していたヘルパーを移行する必要があります。例えば、aws.StringValueaws.ToString に更新する必要があります。

エラー型

AWS SDK for Go は、Go 1.13 で導入されたエラーラッピング機能を最大限に活用します。エラーレスポンスをモデル化しているサービスでは、クライアントの types パッケージに、対応するエラー型が自動生成されています。これらの型を使用することで、クライアントオペレーションのエラーがそれらの型のいずれかによるものかを判定できます。Amazon S3 の GetObject オペレーションでは、存在しないオブジェクトキーを取得しようとすると、NoSuchKey エラーが返される可能性があります。errors.As を使用して、このようなエラーが types.NoSuchKey かどうかを判定できます。サービス側で特定のエラー型がモデル化されていない場合は、smithy.APIError インターフェイス型を利用して、サービスから返されたエラーのコードやメッセージを調べることができます。この機能は、awserr.Error および v1 の他の awserr AWS SDK for Go 機能を置き換えます。エラー処理の詳細については、「AWS SDK for Go V2 でのエラー処理」を参照してください。

// V1 import "github.com/aws/aws-sdk-go/aws/awserr" import "github.com/aws/aws-sdk-go/service/s3" // ... client := s3.New(sess) output, err := s3.GetObject(&s3.GetObjectInput{ // input parameters }) if err != nil { if awsErr, ok := err.(awserr.Error); ok { if awsErr.Code() == "NoSuchKey" { // handle NoSuchKey } else { // handle other codes } return } // handle a error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/service/s3" import "github.com/aws/aws-sdk-go-v2/service/s3/types" import "github.com/aws/smithy-go" // ... client := s3.NewFromConfig(cfg) output, err := client.GetObject(context.TODO(), &s3.GetObjectInput{ // input parameters }) if err != nil { var nsk *types.NoSuchKey if errors.As(err, &nsk) { // handle NoSuchKey error return } var apiErr smithy.APIError if errors.As(err, &apiErr) { code := apiErr.ErrorCode() message := apiErr.ErrorMessage() // handle error code return } // handle error return }

ページネーター

サービスオペレーションページネーターは、サービスクライアントのメソッドとして呼び出されなくなりました。オペレーションにページネーターを使用するには、対応するページネーターコンストラクタメソッドを使用してインスタンスを作成する必要があります。例えば、Amazon S3 の ListObjectsV2 オペレーションをページ分割するには、s3.NewListObjectsV2Paginator を使用してページネーターを作成する必要があります。このコンストラクタは ListObjectsV2Paginator を返します。このページネーターには、取得するページがまだあるかどうかを判定する HasMorePages メソッド、次のページを取得するオペレーションを呼び出す NextPage メソッドが用意されています。SDK ページネーターの使用の詳細については、「オペレーションページネーターの使用」を参照してください。

v1 ページネーターから AWS SDK for Go v2 AWS SDK for Go 同等のページネーターに移行する方法の例を見てみましょう。

// V1 import "fmt" import "github.com/aws/aws-sdk-go/service/s3" // ... client := s3.New(sess) params := &s3.ListObjectsV2Input{ // input parameters } totalObjects := 0 err := client.ListObjectsV2Pages(params, func(output *s3.ListObjectsV2Output, lastPage bool) bool { totalObjects += len(output.Contents) return !lastPage }) if err != nil { // handle error } fmt.Println("total objects:", totalObjects)
// V2 import "context" import "fmt" import "github.com/aws/aws-sdk-go-v2/service/s3" // ... client := s3.NewFromConfig(cfg) params := &s3.ListObjectsV2Input{ // input parameters } totalObjects := 0 paginator := s3.NewListObjectsV2Paginator(client, params) for paginator.HasMorePages() { output, err := paginator.NextPage(context.TODO()) if err != nil { // handle error } totalObjects += len(output.Contents) } fmt.Println("total objects:", totalObjects)

ウェーター

サービスオペレーションのウェーターは、サービスクライアントのメソッドとして呼び出されなくなりました。ウェーターを使用するには、まず必要なウェーター型を作成し、次に wait メソッドを呼び出します。例えば、Amazon S3 のバケットが存在するまで待機するには、BucketExists ウェーターを作成する必要があります。s3.NewBucketExistsWaiter コンストラクタを使用して s3.BucketExistsWaiter を作成します。s3.BucketExistsWaiter には、バケットが使用可能になるまで待機するための Wait メソッドが用意されています。

事前署名リクエスト

V1 SDK は技術的に SDK オペレーション AWS 事前署名をサポートしていましたが、これはサービスレベルで実際にサポートされている内容を正確に表していません (実際には、ほとんどの AWS サービスオペレーションは事前署名をサポートしていません)。

AWS SDK for Go は、サポートされている事前署名可能なオペレーションの特定の APIs を使用してサービスパッケージ内の特定のPresignClient実装を公開することで、これを解決します。

注: SDK v1 で事前署名できていたオペレーションのうち、SDK v2 で事前署名できなくなっているオペレーションがあれば、GitHub に issue を投稿してお知らせください。

PresignPresignRequest の使用箇所は、サービス専用の署名クライアントに置き換える必要があります。

次の例では、S3 GetObject リクエストの事前署名を移行する方法を示しています。

// V1 import ( "fmt" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" ) func main() { sess := session.Must(session.NewSessionWithOptions(session.Options{ SharedConfigState: session.SharedConfigEnable, })) svc := s3.New(sess) req, _ := svc.GetObjectRequest(&s3.GetObjectInput{ Bucket: aws.String("amzn-s3-demo-bucket"), Key: aws.String("key"), }) // pattern 1 url1, err := req.Presign(20 * time.Minute) if err != nil { panic(err) } fmt.Println(url1) // pattern 2 url2, header, err := req.PresignRequest(20 * time.Minute) if err != nil { panic(err) } fmt.Println(url2, header) }
// V2 import ( "context" "fmt" "time" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" ) func main() { cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { panic(err) } svc := s3.NewPresignClient(s3.NewFromConfig(cfg)) req, err := svc.PresignGetObject(context.Background(), &s3.GetObjectInput{ Bucket: aws.String("amzn-s3-demo-bucket"), Key: aws.String("key"), }, func(o *s3.PresignOptions) { o.Expires = 20 * time.Minute }) if err != nil { panic(err) } fmt.Println(req.Method, req.URL, req.SignedHeader) }

リクエストのカスタマイズ

モノリシックだった request.Request API が機能ごとに再分割されました。

オペレーションの入力/出力

オペレーションの入力および出力構造体をそれぞれ保持する不透明な Request フィールド ParamsData は、特定のミドルウェアフェーズ内で入力/出力としてアクセスできるようになりました。

Request.ParamsRequest.Data を参照するリクエストハンドラーはミドルウェアに移行する必要があります。

Params の移行

// V1 import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" ) func withPutObjectDefaultACL(acl string) request.Option { return func(r *request.Request) { in, ok := r.Params.(*s3.PutObjectInput) if !ok { return } if in.ACL == nil { in.ACL = aws.String(acl) } r.Params = in } } func main() { sess := session.Must(session.NewSession()) sess.Handlers.Validate.PushBack(withPutObjectDefaultACL(s3.ObjectCannedACLBucketOwnerFullControl)) // ... }
// V2 import ( "context" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) type withPutObjectDefaultACL struct { acl types.ObjectCannedACL } // implements middleware.InitializeMiddleware, which runs BEFORE a request has // been serialized and can act on the operation input var _ middleware.InitializeMiddleware = (*withPutObjectDefaultACL)(nil) func (*withPutObjectDefaultACL) ID() string { return "withPutObjectDefaultACL" } func (m *withPutObjectDefaultACL) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( out middleware.InitializeOutput, metadata middleware.Metadata, err error, ) { input, ok := in.Parameters.(*s3.PutObjectInput) if !ok { return next.HandleInitialize(ctx, in) } if len(input.ACL) == 0 { input.ACL = m.acl } in.Parameters = input return next.HandleInitialize(ctx, in) } // create a helper function to simplify instrumentation of our middleware func WithPutObjectDefaultACL(acl types.ObjectCannedACL) func (*s3.Options) { return func(o *s3.Options) { o.APIOptions = append(o.APIOptions, func (s *middleware.Stack) error { return s.Initialize.Add(&withPutObjectDefaultACL{acl: acl}, middleware.After) }) } } func main() { cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { // ... } svc := s3.NewFromConfig(cfg, WithPutObjectDefaultACL(types.ObjectCannedACLBucketOwnerFullControl)) // ... }

Data の移行

// V1 import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" ) func readPutObjectOutput(r *request.Request) { output, ok := r.Data.(*s3.PutObjectOutput) if !ok { return } // ... } } func main() { sess := session.Must(session.NewSession()) sess.Handlers.Unmarshal.PushBack(readPutObjectOutput) svc := s3.New(sess) // ... }
// V2 import ( "context" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) type readPutObjectOutput struct{} var _ middleware.DeserializeMiddleware = (*readPutObjectOutput)(nil) func (*readPutObjectOutput) ID() string { return "readPutObjectOutput" } func (*readPutObjectOutput) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( out middleware.DeserializeOutput, metadata middleware.Metadata, err error, ) { out, metadata, err = next.HandleDeserialize(ctx, in) if err != nil { // ... } output, ok := in.Parameters.(*s3.PutObjectOutput) if !ok { return out, metadata, err } // inspect output... return out, metadata, err } func WithReadPutObjectOutput(o *s3.Options) { o.APIOptions = append(o.APIOptions, func (s *middleware.Stack) error { return s.Initialize.Add(&withReadPutObjectOutput{}, middleware.Before) }) } func main() { cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { // ... } svc := s3.NewFromConfig(cfg, WithReadPutObjectOutput) // ... }

HTTP リクエスト/レスポンス

RequestHTTPRequest および HTTPResponse フィールドは特定のミドルウェアフェーズで公開されるようになりました。ミドルウェアはトランスポートに依存しないため、基となる HTTP リクエストまたはレスポンスを明らかにするには、ミドルウェアの入力または出力に対して型アサーションを行う必要があります。

Request.HTTPRequestRequest.HTTPResponse を参照するリクエストハンドラーはミドルウェアに移行する必要があります。

HTTPRequest の移行

// V1 import ( "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/session" ) func withHeader(header, val string) request.Option { return func(r *request.Request) { request.HTTPRequest.Header.Set(header, val) } } func main() { sess := session.Must(session.NewSession()) sess.Handlers.Build.PushBack(withHeader("x-user-header", "...")) svc := s3.New(sess) // ... }
// V2 import ( "context" "fmt" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" ) type withHeader struct { header, val string } // implements middleware.BuildMiddleware, which runs AFTER a request has been // serialized and can operate on the transport request var _ middleware.BuildMiddleware = (*withHeader)(nil) func (*withHeader) ID() string { return "withHeader" } func (m *withHeader) HandleBuild(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) ( out middleware.BuildOutput, metadata middleware.Metadata, err error, ) { req, ok := in.Request.(*smithyhttp.Request) if !ok { return out, metadata, fmt.Errorf("unrecognized transport type %T", in.Request) } req.Header.Set(m.header, m.val) return next.HandleBuild(ctx, in) } func WithHeader(header, val string) func (*s3.Options) { return func(o *s3.Options) { o.APIOptions = append(o.APIOptions, func (s *middleware.Stack) error { return s.Build.Add(&withHeader{ header: header, val: val, }, middleware.After) }) } } func main() { cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { // ... } svc := s3.NewFromConfig(cfg, WithHeader("x-user-header", "...")) // ... }

ハンドラーフェーズ

SDK v2 のミドルウェアフェーズは v1 のハンドラーフェーズの後継にあたります。

次の表では、v1 ハンドラーフェーズと、V2 ミドルウェアスタック内の同等の場所との大まかな対応関係を示しています。

v1 ハンドラー名 v2 ミドルウェアフェーズ
検証 Initialize
構築 Serialize
Sign Finalize
送信 該当なし (1)
ValidateResponse Deserialize
Unmarshal Deserialize
UnmarshalMetadata Deserialize
UnmarshalError Deserialize
再試行 Finalize ("Retry" ミドルウェアの後) (2)
AfterRetry Finalize ("Retry" ミドルウェアの前、next.HandleFinalize() の後) (2、3)
CompleteAttempt Finalize (ステップの末尾)
完了 Initialize (ステップの先頭、next.HandleInitialize() の後) (3)

(1) v1 での Send フェーズは実質的に、v2 ではラップされた HTTP クライアントのラウンドトリップに相当します。この動作はクライアントオプションの HTTPClient フィールドによって制御されます。

(2) Finalize ステップの "Retry" ミドルウェア以降のすべてのミドルウェアは、再試行ループの一部となります。

(3) 実行時のミドルウェア「スタック」は、繰り返し修飾されるハンドラー関数に組み込まれます。各ハンドラーには、チェーン内の次のハンドラーを呼び出す責任があります。これは暗黙的に、ミドルウェアステップが「次のステップ」を呼び出した後にもアクションを実行できることを意味します。

例えば、スタックのトップレベルにある Initialize ステップでは、「次のハンドラーを呼び出した後に動作する」Initialize ミドルウェアは、実質的にリクエストの末尾で動作することになります。

// V2 import ( "context" "github.com/aws/smithy-go/middleware" ) type onComplete struct{} var _ middleware.InitializeMiddleware = (*onComplete)(nil) func (*onComplete) ID() string { return "onComplete" } func (*onComplete) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( out middleware.InitializeOutput, metadata middleware.Metadata, err error, ) { out, metadata, err = next.HandleInitialize(ctx, in) // the entire operation was invoked above - the deserialized response is // available opaquely in out.Result, run post-op actions here... return out, metadata, err }

機能

Amazon EC2 インスタンスメタデータサービス

AWS SDK for Go には、Amazon EC2 インスタンスでアプリケーションを実行するときにローカル IMDS をクエリするために使用できる Amazon EC2 インスタンスメタデータサービス (IMDS) クライアントが用意されています。IMDS クライアントは、アプリケーションに追加できる個別の Go モジュールです。

go get github.com/aws/aws-sdk-go-v2/feature/ec2/imds

クライアントのコンストラクタとメソッドオペレーションは、他の SDK サービスクライアントの設計に合わせて更新されました。

// V1 import "github.com/aws/aws-sdk-go/aws/ec2metadata" // ... client := ec2metadata.New(sess) region, err := client.Region() if err != nil { // handle error }
// V2 import "context" import "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" // ... client := imds.NewFromConfig(cfg) region, err := client.GetRegion(context.TODO()) if err != nil { // handle error }

Amazon S3 Transfer Manager

Amazon S3 Transfer Manager は、オブジェクトのアップロードとダウンロードを同時に管理するために使用できます。このパッケージは、サービスクライアントのインポートパス外にある Go モジュール内にあります。このモジュールは go get github.com/aws/aws-sdk-go-v2/feature/s3/manager を使用して取得できます。

s3.NewUploaders3.NewUploaderWithClient は、アップロードマネージャークライアントを作成するためのコンストラクタメソッド manager.NewUploader に置き換えられました。

s3.NewDownloaders3.NewDownloaderWithClient は、ダウンロードマネージャークライアントを作成するためのコンストラクタメソッド manager.NewDownloader に置き換えられました。

Amazon CloudFront 署名ユーティリティ

AWS SDK for Go は、サービスクライアントのインポートパス外の Go モジュールに Amazon CloudFront 署名ユーティリティを提供します。このモジュールは go get を使用して取得できます。

go get github.com/aws/aws-sdk-go-v2/feature/cloudfront/sign

Amazon S3 暗号化クライアント

以降 AWS SDK for Go、Amazon S3 暗号化クライアントは AWS Crypto Tools の別のモジュールです。Go 用の S3 暗号化クライアントの最新バージョン 3.x が GitHub で公開されています。このモジュールは go get を使用して取得できます。

go get github.com/aws/amazon-s3-encryption-client-go/v3

従来の EncryptionClient (v1v2) と DecryptionClient (v1v2) の各 API は、暗号化と復号の両機能を公開する 1 つのクライアント S3EncryptionClientV3 に統合されました。

の他のサービスクライアントと同様に AWS SDK for Go、オペレーション APIsは要約されています。

  • GetObjectGetObjectRequest、および GetObjectWithContext 復号 API は GetObject に置き換えられました。

  • PutObjectPutObjectRequest、および PutObjectWithContext 暗号化 API は PutObject に置き換えられました。

暗号化クライアントのメジャーバージョン 3.x への移行方法については、このガイドを参照してください。

サービスカスタマイズの変更点

Amazon S3

v1 から AWS SDK for Go v2 に移行する場合、注意すべき重要な変更には、お客様が用意したキーによるサーバー側の暗号化 (SSE-C) SSECustomerKeyに使用される の処理が含まれます。 AWS SDK for Go v1 では、 の Base64 SSECustomerKeyへのエンコードは SDK によって内部的に処理されました。SDK v2 ではこの自動エンコード機能は廃止され、SDK に渡す前に手動で SSECustomerKey を Base64 エンコードする必要があります。

調整例:

// V1 import ( "context" "encoding/base64" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" ) // ... more code plainTextKey := "12345678901234567890123456789012" // 32 bytes in length // calculate md5.. _, err = client.PutObjectWithContext(context.Background(), &s3.PutObjectInput{ Bucket: aws.String("amzn-s3-demo-bucket"), Key: aws.String("your-object-key"), Body: strings.NewReader("hello-world"), SSECustomerKey: &plainTextKey, SSECustomerKeyMD5: &base64Md5, SSECustomerAlgorithm: aws.String("AES256"), }) // ... more code
// V2 import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" ) // ... more code plainTextKey := "12345678901234567890123456789012" // 32 bytes in length base64EncodedKey := base64.StdEncoding.EncodeToString([]byte(plainTextKey)) // calculate md5.. _, err = client.PutObject(context.Background(), &s3.PutObjectInput{ Bucket: aws.String("amzn-s3-demo-bucket"), Key: aws.String("your-object-key"), Body: strings.NewReader("hello-world"), SSECustomerKey: &base64EncodedKey, SSECustomerKeyMD5: &base64Md5, SSECustomerAlgorithm: aws.String("AES256"), }) // ... more code