本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
迁移到 适用于 Go 的 AWS SDK v2
最低 Go 版本
适用于 Go 的 AWS SDK 需要最低版本的 Go 1.23。可以在下载
模块化
适用于 Go 的 AWS SDK 已更新,以利用 Go 模块的优势,该模块已成为 Go 1.13 中的默认开发模式。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,会话。 NewSessionNewSessionWithOptions、和 session.必须迁移到配置中。 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 }
NewSession 使用 AWS.config 选项从中迁移
该示例演示了如何在配置加载期间迁移 aws.Config 值的覆盖。可以向 config.LoadDefaultConfig 提供一个或多个 config.With* 帮助程序函数来覆盖加载的配置值。在此示例中, AWS 区域被重写为us-west-2使用配置。 WithRegion
// 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 提供零个或多个 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) }
有关更多信息,请参阅使用适用于 Go 的 AWS SDK v2 进行单元测试。
凭证和凭证提供程序
aws/credentials 程序包和关联的凭证提供程序已重新定位到 credentialscredentials 程序包是一个 Go 模块,您可以使用 go get 来检索该模块。
go get github.com/aws/aws-sdk-go-v2/credentials
适用于 Go 的 AWS SDK v2 版本更新了 AWS 凭证提供程序,为检索 AWS
凭证提供了一致的接口。每个提供商都实现了 a ws。 CredentialsProviderRetrieve定义了一个返回(aws.Credentials, error). AWS.Credentials 类似于 v1 凭证.
必须使用 a w aws.CredentialsProvider s 包装对象。 CredentialsCacheaws.CredentialsCache对象。默认情况下,使用 aws.CredentialsCache 对由 config.LoadDefaultConfig 配置的凭证进行包装。
下表列出了从 适用于 Go 的 AWS SDK v1 到 v2 的 AWS 证书提供商的位置变化。
| Name | V1 导入 | V2 导入 |
|---|---|---|
| 亚马逊 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
|
静态凭证
使用凭证的应用程序。 NewStaticCredentials要以编程方式构造静态凭证,必须使用证书。 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 }
亚马逊 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
进程凭证
必须迁移NewCredentialsNewCredentialsCommand、和的使用NewCredentialsTimeout才能使用NewProvider
processcreds 程序包的 NewProvider 函数采用字符串参数(要在主机环境的 shell 中执行的命令)和 Options
NewProviderCommand采用接口的实现,该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
必须使用 STS.Clientstscreds包的NewAssumeRoleProvider函数,并使用提供sts.Client者配置的凭据假设角色 AWS Identity and Access Management ARN。您还可以提供一组的功能选项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
必须迁移NewWebIdentityCredentialsNewWebIdentityRoleProvider、和的使用NewWebIdentityRoleProviderWithToken才能使用NewWebIdentityRoleProvider
必须使用 sts.Clientstscreds包的NewWebIdentityRoleProvider函数,并使用提供者配置的凭据来假设角色 AWS Identity and Access Management ARN,以及IdentityTokenRetrieversts.Client 2.0 或 OAuth OpenID Connect ID 令牌的实现。 IdentityTokenFileIdentityTokenRetriever用来从位于应用程序主机文件系统上的文件中提供 Web 身份令牌。您还可以提供一组功能选项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 }
客户端服务
适用于 Go 的 AWS SDK 提供嵌套在github.com/aws/aws-sdk-go-v2/service导入路径下的服务客户端模块。每个服务客户端都包含在一个 Go 程序包中,该程序包使用每项服务的唯一标识符进行标识。下表提供了 适用于 Go 的 AWS SDK中服务导入路径的一些示例。
| 服务名称 | 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 日志 |
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
客户端构造
您可以使用客户端包中的 适用于 Go 的 AWS SDK New或NewFromConfig构造函数在中构造客户端。从 适用于 Go 的 AWS SDK v1 迁移时,我们建议您使用NewFromConfig变体,该变体将使用中的值返回新的服务客户端。aws.Config在使用 config.LoadDefaultConfig 加载 SDK 共享配置时将会创建 aws.Config 值。有关创建服务客户端的详细信息,请参阅将适用于 Go 的 AWS SDK 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 程序包不再存在于 适用于 Go 的 AWS SDK中。现在,每个服务客户端都将其所需的 AWS 端点元数据嵌入到客户端包中。这样就不再包含应用程序未使用的服务的端点元数据,从而减少了已编译应用程序的总体二进制文件大小。
此外,每项服务现在都提供自己的接口,用于在 EndpointResolverV2 中进行端点解析。每个 API 都会针对服务 EndpointParameters 采用一组独特的参数,这些参数的值由 SDK 在调用操作时从不同位置获取。
默认情况下,服务客户端使用其配置的 AWS 区域来解析目标区域的服务终端节点。如果您的应用程序需要自定义端点,则可在 aws.Config 结构上的 EndpointResolverV2 字段中指定自定义行为。如果您的应用程序实现了自定义 endpoints.Resolver,则必须将其迁移以符合这个新的按服务划分的接口。
有关端点以及如何实施自定义解析器的更多信息,请参阅配置客户端端点。
身份验证
适用于 Go 的 AWS SDK 支持更高级的身份验证行为,从而允许使用较新的 AWS 服务功能,例如 codecatalyst 和 S3 Express One Zone Zone。此外,可以针对每个客户端对此行为进行自定义。
调用 API 操作
服务客户端操作方法的数量已大幅减少。<OperationName>Request、<OperationName>WithContext 和 <OperationName> 方法均已合并为单个操作方法 <OperationName>。
示例
以下示例显示了如何将对 Amazon S3 PutObject 操作的调用从 适用于 Go 的 AWS SDK 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 操作的输入和输出形状PutObjectOutput
除输入和输出类型之外的所有其他服务数据类型均已迁移到位于服务客户端程序包导入路径层次结构下的 types 程序包中。例如,s 3。 AccessControlPolicytype 现在位于 typ es。 AccessControlPolicy
枚举值
SDK 现在为所有 API 枚举字段提供类型化体验。现在,您可以使用服务客户端 types 程序包中的一种具体类型,而不是使用从服务 API 参考文档中复制的字符串文本值。例如,您可以为 Amazon S3 PutObjectInput 操作提供要应用于对象的 ACL。在 适用于 Go 的 AWS SDK v1 中,此参数是一种*string类型。在中 适用于 Go 的 AWS SDK,此参数现在是类型。 ObjectCannedACLtypes 程序包为可以分配给该字段的有效枚举值提供了生成的常量。例如类型。 ObjectCannedACLPrivate
指针参数
适用于 Go 的 AWS SDK v1 要求将所有输入参数的指针引用传递给服务操作。 适用于 Go 的 AWS SDK v2 无需尽可能将输入值作为指针传递,从而简化了大多数服务的体验。此更改意味着许多服务客户端操作不再要求您的应用程序传递以下类型的指针引用:uint8、uint16、uint32、int8、int16、int32、float32、float64、bool。同样,切片和映射元素类型已相应更新,以反映其元素是否必须作为指针引用传递。
awsstring 转换为 *string。相反,a ws。 ToString*string ⇒ 转换string。将应用程序从 适用于 Go 的 AWS SDK v1 升级到 v2 时,必须迁移帮助程序的使用情况,以便从指针类型转换为非指针变体。例如,aw s。 StringValue必须更新为aws.ToString。
错误类型
充分 适用于 Go 的 AWS SDK 利用了 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 分页器的更多详细信息,请访问使用操作分页器。
让我们来看一个如何从 适用于 Go 的 AWS SDK v1 分页器迁移到 v2 等效分页器的示例。 适用于 Go 的 AWS SDK
示例
// 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)
Waiter
不再将服务操作 Waiter 作为服务客户端上的方法进行调用。要使用 Waiter,首先要构造所需的 Waiter 类型,然后调用 wait 方法。例如,要等待 Amazon S3 存储桶存在,您必须构造一个 BucketExists Waiter。使用 s 3。 NewBucketExistsWaiters3.BucketExistsWaiter 提供了 Wait 方法,可用于等待存储桶变为可用状态。
预签名请求
从技术上讲,V1 SD AWS K 支持对任何 SDK 操作进行预签名,但是,这并不能准确表示服务级别实际支持的内容(实际上,大多数 AWS 服务操作都不支持预签名)。
适用于 Go 的 AWS SDK 通过在服务包中公开特定于支持的预签名操作的特定PresignClient APIs 实现来解决这个问题。
注意:如果某项服务缺少对您在 SDK v1 中成功使用的操作的预签名支持,请通过向上提交问题
使用 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 中间件阶段 |
|---|---|
| 验证 | 初始化 |
| 构建 | 序列化 |
| 签名 | 最终确定 |
| 发送 | n/a (1) |
| ValidateResponse | 反序列化 |
| 解组 | 反序列化 |
| UnmarshalMetadata | 反序列化 |
| UnmarshalError | 反序列化 |
| 重试 | 最终确定,在 "Retry" 中间件之后(2) |
| AfterRetry | 最终确定,在 "Retry" 中间件之前,在 next.HandleFinalize() 之后(2、3) |
| CompleteAttempt | 最终确定,步骤结束 |
| 完成 | 初始化,步骤开始,next.HandleInitialize() 之后(3) |
(1)v1 中的 Send 阶段实际上是 v2 中包装的 HTTP 客户端往返行程。此行为由客户端选项上的 HTTPClient 字段控制。
(2)“最终确定”步骤中 "Retry" 中间件之后的任何中间件都将是重试循环的一部分。
(3)操作时的中间件“堆栈”内置在重复装饰的处理程序函数中。每个处理程序都负责调用链中的下一个处理程序。这实际上意味着中间件步骤也可以在其下一步骤调用之后执行操作。
例如,对于堆栈顶部的“初始化”步骤,这意味着在调用下一个处理程序后执行操作的初始化中间件实际上是在请求结束时才运行:
// 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 实例元数据服务
适用于 Go 的 AWS SDK 提供了亚马逊 EC2 实例元数据服务 (IMDS) 客户端,在亚马逊实例上执行应用程序时,您可以使用该客户端查询本地 IMDS。 EC2 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已被构造函数方法管理器所取代。 NewUploader
s3。 NewDownloader和 s3。 NewDownloaderWithClient已被单个构造函数方法管理器所取代。 NewDownloader
Amazon CloudFront 签名工具
在服务客户端导入路径之外的 Go 模块中 适用于 Go 的 AWS SDK 提供 Amazon CloudFront 签名实用程序。可以使用 go get 来检索此模块。
go get github.com/aws/aws-sdk-go-v2/feature/cloudfront/sign
Amazon S3 加密客户端
首先 适用于 Go 的 AWS SDK,Amazon S3 加密客户端是AWS 加密工具下的独立模块。适用于 Go 的 S3 加密客户端 3.x 的最新版本现已在上GitHubgo get 来检索此模块:
go get github.com/aws/amazon-s3-encryption-client-go/v3
单独的EncryptionClient(v1、v2)和DecryptionClient(v1、v 2) APIs 已被单个客户端 S3 EncryptionClient V 3
像中的其他服务客户一样 适用于 Go 的 AWS SDK,该操作 APIs 已被压缩:
要了解如何迁移到加密客户端的 3.x 主要版本,请参阅本指南。
服务自定义更改
Amazon S3
从 适用于 Go 的 AWS SDK v1 迁移到 v2 时,需要注意的一个重要变化涉及使用客户提供的密钥 (SSE-C) 处理SSECustomerKey用于服务器端加密的内容。在 适用于 Go 的 AWS SDK v1 中,SSECustomerKey到 Base64 的编码由软件开发工具包内部处理。在 SDK v2 中,这种自动编码功能已被删除,现在需要手动将 SSECustomerKey 编码为 Base64,然后再将其传递给 SDK。
示例调整:
// 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