翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
v2 AWS SDK for Go への移行
Go の最小バージョン要件
には、Go 1.23 の最小バージョン AWS SDK for Go が必要です。Go の最新バージョンは「Downloads
モジュール化
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 パッケージとその関連機能は、configconfig パッケージは個別の Go モジュールであり、go get を使用してアプリケーションの依存関係に含めることができます。
go get github.com/aws/aws-sdk-go-v2/config
session.New、session.NewSession、NewSessionWithOptions、および session.Must は config.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.WithRegionus-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 パッケージおよび関連する認証情報プロバイダーは credentialscredentials パッケージは Go モジュールであり、go get を使用して取得します。
go get github.com/aws/aws-sdk-go-v2/credentials
AWS SDK for Go v2 リリースでは AWS 、認証情報プロバイダーが更新され、認証情報を取得 AWS するための一貫したインターフェイスが提供されます。各プロバイダーは aws.CredentialsProvider(aws.Credentials, error).Value タイプに類似した . aws.CredentialsRetrieveメソッドを定義します。
認証情報のキャッシュを行うには、aws.CredentialsProvider オブジェクトを aws.CredentialsCacheaws.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
例
// 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
プロセス認証情報
NewCredentials、NewCredentialsCommand、NewCredentialsTimeout の使用は NewProvider
processcreds パッケージの NewProvider 関数は、ホスト環境のシェルで実行するコマンドの文字列引数と、Options
NewProviderCommand は、より複雑なプロセスコマンド (1 つ以上のコマンドライン引数を取るものや、特定の実行環境要件があるものなど) を定義する NewCommandBuilder
例
// 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.Clientsts.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
NewWebIdentityCredentials、NewWebIdentityRoleProvider、NewWebIdentityRoleProviderWithToken の使用は NewWebIdentityRoleProvider
stscreds パッケージの NewWebIdentityRoleProvider関数は、sts.Clientsts.Clientの設定済み認証情報を使用して引き受ける AWS Identity and Access Management ロール ARN、および OAuth 2.0 または OpenID Connect ID トークンを提供するための IdentityTokenRetrieverIdentityTokenRetriever です。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.Config。aws.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
入力および出力型以外のすべてのサービスデータ型は、サービスクライアントパッケージのインポートパス階層下にある types パッケージに移行されました。例えば、s3.AccessControlPolicy 型は現在、types.AccessControlPolicy
列挙値
SDK では、すべての API の列挙型フィールドに対して、型付きで扱えるようになりました。サービス API リファレンスドキュメントからコピーした文字列リテラル値を使用する代わりに、サービスクライアントの types パッケージにある具象型を使用できます。例えば、Amazon S3 の PutObjectInput オペレーションに対して、オブジェクトに適用する ACL を指定できます。 AWS SDK for Go v1 では、このパラメータは *string型でした。 AWS SDK for Goでは、このパラメータは types.ObjectCannedACLtypes パッケージには、このフィールドに指定できる有効な列挙値に対応する定数が自動生成されています。例えば、types.ObjectCannedACLPrivate
ポインタパラメータ
AWS SDK for Go v1 では、すべての入力パラメータに対してサービスオペレーションに渡されるポインタリファレンスが必要でした。 AWS SDK for Go v2 では、入力値をポインタとして渡す必要がなくなるため、ほとんどの サービスのエクスペリエンスが簡素化されました。この変更により、多くのサービスクライアントオペレーションで uint8、uint16、uint32、int8、int16、int32、float32、float64、bool の各型に対するポインタ参照を渡す必要がなくなりました。同様に、スライスとマップの要素型も、要素をポインタ参照として渡す必要があるかどうかに応じて更新されました。
awsstring ⇒ *string の変換を行います。逆に、aws.ToString*string ⇒ string の変換を行います。アプリケーションを AWS SDK for Go v1 から v2 にアップグレードする際は、ポインタ型から非ポインタ型への変換に使用していたヘルパーを移行する必要があります。例えば、aws.StringValue は aws.ToString に更新する必要があります。
エラー型
AWS SDK for Go は、Go 1.13 で導入されたエラーラッピング機能を最大限に活用しますtypes パッケージに、対応するエラー型が自動生成されています。これらの型を使用することで、クライアントオペレーションのエラーがそれらの型のいずれかによるものかを判定できます。Amazon S3 の GetObject オペレーションでは、存在しないオブジェクトキーを取得しようとすると、NoSuchKey エラーが返される可能性があります。errors.As
例
// 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.NewListObjectsV2PaginatorHasMorePages メソッド、次のページを取得するオペレーションを呼び出す 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.NewBucketExistsWaiters3.BucketExistsWaiter には、バケットが使用可能になるまで待機するための Wait メソッドが用意されています。
事前署名リクエスト
V1 SDK は技術的に SDK オペレーションの AWS 事前署名をサポートしていましたが、これはサービスレベルで実際にサポートされている内容を正確に表していません (実際には、ほとんどの AWS サービスオペレーションは事前署名をサポートしていません)。
AWS SDK for Go は、サポートされている事前署名可能なオペレーションの特定の APIs を使用してサービスパッケージ内の特定のPresignClient実装を公開することで、これを解決します。
注: SDK v1 で事前署名できていたオペレーションのうち、SDK v2 で事前署名できなくなっているオペレーションがあれば、GitHub に issue を投稿
Presign や PresignRequest の使用箇所は、サービス専用の署名クライアントに置き換える必要があります。
次の例では、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 フィールド Params と Data は、特定のミドルウェアフェーズ内で入力/出力としてアクセスできるようになりました。
Request.Params と Request.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 リクエスト/レスポンス
Request の HTTPRequest および HTTPResponse フィールドは特定のミドルウェアフェーズで公開されるようになりました。ミドルウェアはトランスポートに依存しないため、基となる HTTP リクエストまたはレスポンスを明らかにするには、ミドルウェアの入力または出力に対して型アサーションを行う必要があります。
Request.HTTPRequest と Request.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.NewUploader と s3.NewUploaderWithClient は、アップロードマネージャークライアントを作成するためのコンストラクタメソッド manager.NewUploader
s3.NewDownloader と s3.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 が GitHubgo get を使用して取得できます。
go get github.com/aws/amazon-s3-encryption-client-go/v3
従来の EncryptionClient (v1、v2) と DecryptionClient (v1、v2) の各 API は、暗号化と復号の両機能を公開する 1 つのクライアント S3EncryptionClientV3
の他のサービスクライアントと同様に AWS SDK for Go、オペレーション APIsは要約されています。
暗号化クライアントのメジャーバージョン 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