

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 配置 SDK
<a name="configure-gosdk"></a>

 在 适用于 Go 的 AWS SDK V2 中，您可以为服务客户端配置常用设置，例如记录器、日志级别和重试配置。大多数设置都是可选的。但是，对于每个服务客户端，您必须指定一个 AWS 区域和您的证书。SDK 使用这些值将请求发送到正确的区域，并使用正确的凭证对请求进行签名。您可以在代码中以编程方式指定这些值，也可以通过执行环境指定这些值。

## 加载 AWS 共享配置文件
<a name="loading-aws-shared-configuration"></a>

 有多种方法可以初始化服务 API 客户端，但下面这种是向用户推荐的最常见模式。

 要将 SDK 配置为使用 AWS 共享配置文件，请使用以下代码：

```
import (
  "context"
  "log"
  "github.com/aws/aws-sdk-go-v2/config"
)

// ...

cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
  log.Fatalf("failed to load configuration, %v", err)
}
```

 `config.LoadDefaultConfig(context.TODO())`将使用 AWS 共享[配置源构建 AWS.config。](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Config)这包括配置凭证提供商、配置 AWS 区域和加载特定于服务的配置。可以使用加载的 `aws.Config` 来构造服务客户端，这为构造客户端提供了一致的模式。

 有关 AWS 共享配置文件的更多信息，请参阅 AWS SDKs 和工具参考指南中的[配置](https://docs.aws.amazon.com/sdkref/latest/guide/creds-config-files.html)。

## 指定 AWS 区域
<a name="specifying-the-aws-region"></a>

 指定区域时，您指定将请求发送到何处，例如 `us-west-2` 或 `us-east-2`。要查看每项服务的区域列表，请参阅《 Amazon Web Services 一般参考》中的[服务端点和配额](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html)。

 SDK 没有默认区域。指定一个区域：
+  将 `AWS_REGION` 环境变量设置为默认区域。
+  使用[配置明确设置区域。 WithRegion](https://github.com/aws/aws-sdk-go-v2/blob/config/v0.2.2/config/provider.go#L127)作为加载配置`config.LoadDefaultConfig`时的参数。

 评论：如果您使用所有这些方法来设置区域，则 SDK 将使用您显式指定的区域。

### 使用环境变量配置区域
<a name="configure-region-with-environment-variable"></a>

#### Linux、macOS 或 Unix
<a name="linux-macos-or-unix"></a>

```
export AWS_REGION=us-west-2
```

#### Windows
<a name="windows"></a>

```
set AWS_REGION=us-west-2
```

### 以编程方式指定区域
<a name="specify-region-programmatically"></a>

```
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-west-2"))
```

## 指定凭证
<a name="specifying-credentials"></a>

 适用于 Go 的 AWS SDK 需要凭证（访问密钥和私有访问密钥）才能对请求进行签名 AWS。根据您的特定使用案例，您可以在多个位置指定凭证。有关获取凭证的信息，请参阅[开始使用 适用于 Go 的 AWS SDK](getting-started.md)。

 当您使用初始化`aws.Config`实例时`config.LoadDefaultConfig`，SDK 会使用其默认凭证链来查找 AWS 凭证。此默认凭证链按以下顺序查找凭证：

1.  环境变量。

   1.  静态凭证（`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`、`AWS_SESSION_TOKEN`） 

   1.  Web 身份令牌（`AWS_WEB_IDENTITY_TOKEN_FILE`） 

1.  共享配置文件。

   1.  SDK 默认为计算机主文件夹中的 `.aws` 文件夹下的 `credentials` 文件。

   1.  SDK 默认为计算机主文件夹中的 `.aws` 文件夹下的 `config` 文件。

1.  如果您的应用程序使用 Amazon ECS 任务定义或 RunTask API 操作，则使用 IAM 角色执行任务。

1.  适用于 Amazon EC2 的 IAM 角色（如果您的应用程序在 Amazon EC2 实例上运行）。

 SDK 自动检测并使用内置提供程序，无需进行手动配置。例如，如果您使用适用于 Amazon EC2 实例的 IAM 角色，则您的应用程序会自动使用该实例的凭证。无需在应用程序中手动配置凭证。

 作为最佳实践， AWS 建议您按以下顺序指定凭证：

1.  如果您的应用程序使用 Amazon ECS 任务定义或 RunTask API 操作，请使用 IAM 角色执行任务。

1.  如果您的应用程序在 Amazon EC2 实例上运行，请使用适用于 Amazon EC2 的 IAM 角色。

    IAM 角色为实例上的应用程序提供临时安全证书以进行 AWS 调用。IAM 角色提供了一种简便方法，用于在多个 Amazon EC2 实例上分发和管理凭证。

1.  使用共享凭证或配置文件。

    凭据和配置文件在其他 AWS SDKs 和之间共享 AWS CLI。作为安全最佳实践，我们建议使用凭证文件来设置敏感值，例如访问密钥 IDs 和密钥。这里有上述每个文件的[格式要求](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html)。

1.  使用环境变量。

    如果您是在 Amazon EC2 实例以外的计算机上进行开发工作，则设置环境变量非常有用。

### 任务的 IAM 角色
<a name="iam-roles-for-tasks"></a>

 如果您的应用程序使用 Amazon ECS 任务定义或 `RunTask` 操作，请使用[任务 IAM 角色](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)指定任务中容器可以使用的 IAM 角色。

### 适用于 Amazon EC2 实例的 IAM 角色
<a name="iam-roles-for-ec2-instances"></a>

 如果您正在 Amazon EC2 实例上运行应用程序，请使用该实例的 [IAM 角色](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)获取临时安全凭证以调用 AWS。

 如果您已将实例配置为使用 IAM 角色，则 SDK 会自动将这些凭证用于您的应用程序。您无需手动指定这些凭证。

### 共享凭证和配置
<a name="shared-credentials-and-configuration"></a>

 共享的凭据和配置文件可用于在其他工具 AWS SDKs 之间共享通用配置。如果您对不同的工具或应用程序使用不同的凭证，则可以使用*配置文件*在相同的配置文件中配置多个访问密钥。

 您可以使用 `config.LoadOptions` 提供多个凭证或配置文件位置，默认情况下，SDK 会加载存储在[指定凭证](#specifying-credentials)中提及的默认位置处的文件。

```
import (
    "context"
    "github.com/aws/aws-sdk-go-v2/config"    
)

// ...

cfg , err := config.LoadDefaultConfig(context.TODO(), 
    config.WithSharedCredentialsFiles(
    []string{"test/credentials", "data/credentials"},
    ), 
    config.WithSharedConfigFiles(
        []string{"test/config", "data/config"},
    )   
)
```

 使用共享凭证和配置文件时，如果指定了重复的配置文件，则会将其合并以解析一个配置文件。在发生合并冲突的情况下，

1.  如果在同一个文件中指定了重复的配置 credentials/config 文件，则在后一个配置文件中指定的配置文件属性优先。

1.  如果在多个凭证文件或多个配置文件中指定了重复的配置文件，则将按照 `config.LoadOptions` 的文件输入顺序解析配置文件属性。后面文件中的配置文件属性优先。

1.  如果凭证文件和配置文件中都存在配置文件，则凭证文件属性优先。

 如果需要，可以启用 `config.LoadOptions` 上的 `LogConfigurationWarnings`，并记录配置文件解析步骤。

#### 创建凭证文件
<a name="creating-the-credentials-file"></a>

 如果没有共享凭证文件（`.aws/credentials`），可以使用任何文本编辑器在主目录中创建一个该文件。将以下内容添加到您的凭据文件中，用您的*<YOUR\$1SECRET\$1ACCESS\$1KEY>*凭据替换*<YOUR\$1ACCESS\$1KEY\$1ID>*和。

```
[default]
aws_access_key_id = <YOUR_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>
```

 `[default]` 标题定义了默认配置文件的凭证，除非您将其配置为使用其他配置文件，否则 SDK 将使用默认配置文件。

 您也可以通过将会话令牌添加到配置文件来使用临时安全凭证，如以下示例所示：

```
[temp]
aws_access_key_id = <YOUR_TEMP_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_TEMP_SECRET_ACCESS_KEY>
aws_session_token = <YOUR_SESSION_TOKEN>
```

 凭证文件中非默认配置文件的部分名称不得以单词 `profile` 开头。您可以在[AWS SDKs 和工具参考指南](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html#file-format-creds)中阅读更多内容。

#### 创建配置文件
<a name="creating-the-config-file"></a>

 如果没有共享凭证文件（`.aws/config`），可以使用任何文本编辑器在主目录中创建一个该文件。将以下内容添加到您的配置文件中，*<REGION>*替换为所需的区域。

```
[default]
region = <REGION>
```

 `[default]` 标题定义了默认配置文件的配置，除非您将其配置为使用其他配置文件，否则 SDK 将使用默认配置文件。

 您可以使用命名配置文件，如以下示例所示：

```
[profile named-profile]
region = <REGION>
```

 配置文件中非默认配置文件的部分名称必须始终以单词 `profile` 开头，后跟预期的配置文件名称。您可以在[AWS SDKs 和工具参考指南](https://docs.aws.amazon.com/credref/latest/refdocs/file-format.html#file-format-config)中阅读更多内容。

#### 指定配置文件
<a name="specifying-profiles"></a>

 您可以在同一配置文件中包含多个访问密钥，方法是将每组访问密钥与一个配置文件进行关联。例如，在凭证文件中，您可以声明多个配置文件，如下所示。

```
[default]
aws_access_key_id = <YOUR_DEFAULT_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_DEFAULT_SECRET_ACCESS_KEY>

[test-account]
aws_access_key_id = <YOUR_TEST_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_TEST_SECRET_ACCESS_KEY>

[prod-account]
; work profile
aws_access_key_id = <YOUR_PROD_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_PROD_SECRET_ACCESS_KEY>
```

 默认情况下，开发工具包会检查 `AWS_PROFILE` 环境变量以确定使用哪些配置文件。如果未设置任何 `AWS_PROFILE` 变量，SDK 将使用 `default` 配置文件。

 有时，您可能想在应用程序中使用不同的配置文件。例如，您想在 `myapp` 应用程序中使用 `test-account` 凭证。可以通过以下命令来使用此配置文件：

```
$ AWS_PROFILE=test-account myapp
```

 您也可以指示 SDK 选择配置文件，方法是在调用 `config.LoadDefaultConfig` 之前调用 `os.Setenv("AWS_PROFILE", "test-account")`，或者将显式配置文件作为参数进行传递，如以下示例所示：

```
cfg, err := config.LoadDefaultConfig(context.TODO(), 
    config.WithSharedConfigProfile("test-account"))
```

**注意**  
如果在环境变量中指定凭证，则无论指定哪个配置文件，SDK 都将始终使用这些凭证。

### 环境变量
<a name="environment-variables"></a>

 默认情况下，SDK 会检测您的环境中设置的 AWS 凭据，并使用这些凭据来签署对的请求 AWS。这样就无需管理应用程序中的凭证。

 SDK 在以下环境变量中查找凭证：
+  `AWS_ACCESS_KEY_ID` 
+  `AWS_SECRET_ACCESS_KEY` 
+  `AWS_SESSION_TOKEN`（可选） 

 以下示例演示了如何配置环境变量。

#### Linux、OS X 或 Unix
<a name="linux-os-x-or-unix"></a>

```
$ export AWS_ACCESS_KEY_ID=YOUR_AKID
$ export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
$ export AWS_SESSION_TOKEN=TOKEN
```

#### Windows
<a name="windows-1"></a>

```
> set AWS_ACCESS_KEY_ID=YOUR_AKID
> set AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
> set AWS_SESSION_TOKEN=TOKEN
```

### 以编程方式指定凭证
<a name="specify-credentials-programmatically"></a>

 `config.LoadDefaultConfig`允许您提供明确的 a [ws。 CredentialProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#CredentialsProvider)加载共享配置源时。要在加载共享配置时传递显式凭据提供程序，请使用 [config。 WithCredentialsProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#WithCredentialsProvider)。例如，如果 `customProvider` 引用了 `aws.CredentialProvider` 实现的一个实例，则可在配置加载期间传递该实例，如下所示：

```
cfg, err := config.LoadDefaultConfig(context.TODO(), 
    config.WithCredentialsProvider(customProvider))
```

 如果您显式提供凭证（如本示例所示），SDK 将仅使用这些凭证。

**注意**  
传递给或返回的所有凭证提供者`LoadDefaultConfig`都将[CredentialsCache](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#CredentialsCache)自动封装在中。这使得缓存和凭证轮换具有并发安全性。如果您`aws.Config`直接在上显式配置提供程序，则还必须使用此类型显式包装提供程序[NewCredentialsCache](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#NewCredentialsCache)。

#### 静态凭证
<a name="static-credentials"></a>

 [您可以使用证书在应用程序中对凭据进行硬编码。 NewStaticCredentialsProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials#NewStaticCredentialsProvider)凭据提供者，用于明确设置要使用的访问密钥。例如：

```
cfg, err := config.LoadDefaultConfig(context.TODO(), 
    config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("AKID", "SECRET_KEY", "TOKEN")),
)
```

**警告**  
 请勿将凭证嵌入到应用程序中。此方法只用于测试目的。

#### 单点登录凭证
<a name="single-sign-on-credentials"></a>

 SDK 提供了一个凭据提供商，用于使用检索临时 AWS 证书。 AWS IAM Identity Center使用 AWS CLI，您可以通过 AWS 访问门户进行身份验证并授权访问临时 AWS 证书。然后，您将应用程序配置为加载单点登录 (SSO) 配置文件，然后 SDK 使用您的 SSO 凭证来检索临时证书，这些 AWS 证书将在过期后自动续订。如果您的 SSO 证书过期，则必须使用再次登录您的 IAM Identity Center 账户，从而明确续订证书。 AWS CLI

 例如，您可以创建配置文件`dev-profile`，使用对该配置文件进行身份验证和授权 AWS CLI，并按如下所示配置您的应用程序。

1.  首先创建 `profile` 和 `sso-session` 

```
[profile dev-profile]
sso_session = dev-session
sso_account_id = 012345678901
sso_role_name = Developer
region = us-east-1

[sso-session dev-session]
sso_region = us-west-2
sso_start_url = https://company-sso-portal.awsapps.com/start
sso_registration_scopes = sso:account:access
```

1.  使用登录对 SSO 配置文件 AWS CLI 进行身份验证和授权。

```
$ aws --profile dev-profile sso login 
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.us-west-2.amazonaws.com/

Then enter the code:

ABCD-EFGH
Successully logged into Start URL: https://company-sso-portal.awsapps.com/start
```

1.  接下来，将应用程序配置为使用 SSO 配置文件。

```
import "github.com/aws/aws-sdk-go-v2/config"

// ...

cfg, err := config.LoadDefaultConfig(
    context.Background(),
    config.WithSharedConfigProfile("dev-profile"),
)
if err != nil {
    return err
}
```

 有关配置 SSO 配置文件和使用进行身份验证的更多信息， AWS CLI 请参阅 AWS CLI 用户[指南 AWS IAM Identity Center中的配置 AWS CLI 以使用](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html)。有关以编程方式构造 SSO 凭证提供程序的更多信息，请参阅 [ssocreds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/ssocreds) API 参考文档。

#### 登录凭证
<a name="login-credentials"></a>

您可以使用现有的 AWS 管理控制台登录凭据以编程方式访问 AWS 服务。在基于浏览器的身份验证流程之后， AWS 生成可在本地开发工具（如 CL AWS I 和）上使用的临时证书。 AWS Tools for PowerShell AWS SDKs此功能简化了配置和管理 AWS CLI 凭证的过程，尤其是在您更喜欢交互式身份验证而不是管理长期访问密钥的情况下。

1. 使用 AWS CLI 启动登录流程，然后按照浏览器提示进行操作。在此示例中，我们将登录会话保存到新的配置文件**dev-profile**中，但这是可选的。

   ```
   $ aws --profile dev-profile login
   ```

1. （可选）检查您的 AWS 共享配置文件以验证会话是否已建立。

   ```
   [profile dev-profile]
   login_session = arn:aws:sts::account id>:role
   ```

1. 接下来，将您的应用程序配置为使用登录配置文件。

   ```
   import "github.com/aws/aws-sdk-go-v2/config"
   
   // ...
   
   cfg, err := config.LoadDefaultConfig(
       context.Background(),
       // only necessary if login session is saved to a non-default profile
       config.WithSharedConfigProfile("dev-profile"),
   )
   if err != nil {
       return err
   }
   ```

有关配置登录配置文件和使用 AWS CLI 进行身份验证的更多信息，请参阅[使用控制台凭据登录 AWS 本地开发](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sign-in.html)。

#### 其他凭证提供程序
<a name="other-credentials-providers"></a>

 SDK 提供了其他方法，用于在[凭证](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials)模块中检索凭证。例如，您可以从加密存储中检索临时安全证书 AWS Security Token Service 或从加密存储中检索证书。

 **可用的凭证提供程序**：
+  [ec2rolecreds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds) – 通过 Amazon EC2 IMDS 从 Amazon EC2 实例角色中检索凭证。
+  [endpointcreds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds) – 从任意 HTTP 端点中检索凭证。
+  [processcreds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/processcreds) – 从将由主机环境的 shell 调用的外部进程中检索凭证。
+  [stscreds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds) — 从中检索证书 AWS STS 

# 配置身份验证
<a name="configure-auth"></a>

 适用于 Go 的 AWS SDK 提供了配置身份验证行为服务的功能。大多数情况下，默认配置就足够了，但是配置自定义身份验证可支持其他行为，例如使用预发布服务功能。

## 定义
<a name="definitions"></a>

 本节简要介绍了适用于 Go 的 AWS SDK 中的身份验证组件。

### AuthScheme
<a name="authscheme"></a>

 [AuthScheme](https://pkg.go.dev/github.com/aws/smithy-go/transport/http#AuthScheme) 是定义一种工作流程的接口，SDK 通过该工作流程检索调用方身份并将其附加到操作请求。

 身份验证方案使用以下组件（详情见下文）：
+  唯一 ID（用于标识该方案） 
+  身份解析器，负责返回签名过程中使用的调用方身份（例如您的 AWS 凭证） 
+  签署人，负责将调用方身份实际注入到操作的传输请求中（例如 `Authorization` HTTP 标头） 

 每个服务客户端选项都包含一个 `AuthSchemes` 字段，默认情况下，其中会填充该服务支持的身份验证方案列表。

### AuthSchemeResolver
<a name="authschemeresolver"></a>

 每个服务客户端选项都包含一个 `AuthSchemeResolver` 字段。这种按服务定义的接口是 SDK 调用的 API，用于确定针对每项操作可能提供的身份验证选项。

**重要**  
 身份验证方案解析器并不决定使用哪种身份验证方案。它返回**可以使用的方案（“选项”）列表，最终方案是通过[此处](#auth-scheme-resolution-workflow)描述的固定算法选择的。

### Option
<a name="option"></a>

 [Option](https://pkg.go.dev/github.com/aws/smithy-go/auth#Option) 是在调用 `ResolverAuthSchemes` 时返回，表示可能的身份验证选项。

 一个选项由以下三组信息组成：
+  代表可能方案的 ID 
+  将提供给该方案身份解析器的一组不透明属性 
+  将提供给方案签署人的一组不透明属性 

#### 关于属性的说明
<a name="a-note-on-properties"></a>

 对于 99% 的使用案例，调用方无需关心身份解析和签名的不透明属性。SDK 将提取每种方案的必要属性，并将它们传递给 SDK 中公开的强类型接口。例如，服务的默认身份验证解析器对 SigV4 选项进行编码，使其具有签名名称和区域的签署人属性，当选择 SigV4 时，这些属性的值将传递到客户端已配置的 [v4.HTTPSigner](https://pkg.go.dev/github.com/aws/smithy-go/auth#Option) 实现。

### Identity
<a name="identity"></a>

 [Identity](https://pkg.go.dev/github.com/aws/smithy-go/auth#Identity) 是对 SDK 调用方身份的抽象表示。

 SDK 中最常用的身份类型是一组 `aws.Credentials`。对于大多数使用案例，调用方无需将自己的 `Identity` 视为抽象概念，可以直接使用具体类型。

**注意**  
 为了保持向后兼容性并防止 API 混淆，AWS 特定于 SDK 的身份类型 `aws.Credentials` 不能直接满足 `Identity` 接口的要求。此映射的处理是在内部进行。

### IdentityResolver
<a name="identityresolver"></a>

 [IdentityResolver](https://pkg.go.dev/github.com/aws/smithy-go/auth#IdentityResolver) 是用于检索 `Identity` 的接口。

 `IdentityResolver` 的具体版本以强类型形式存在于 SDK 中（例如 [aws.CredentialsProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#CredentialsProvider)），SDK 在内部处理此映射。

 调用方只需在定义外部身份验证方案时直接实现 `IdentityResolver` 接口。

### Signer
<a name="signer"></a>

 [Signer](https://pkg.go.dev/github.com/aws/smithy-go/transport/http#Signer) 是一个接口，通过该接口可以用检索到的调用方 `Identity` 来补充请求。

 `Signer` 的具体版本以强类型形式存在于 SDK 中（例如 [v4.HTTPSigner](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/signer/v4#HTTPSigner)），SDK 在内部处理此映射。

 调用方只需在定义外部身份验证方案时直接实现 `Signer` 接口。

### AuthResolverParameters
<a name="authresolverparameters"></a>

 每项服务都需要一组特定的输入，这些输入将传递给其解析函数，此函数在每个服务包中定义为 `AuthResolverParameters`。

 基本解析器参数如下所示：


|  名称  |  类型  |  描述  | 
| --- | --- | --- | 
|  Operation  |  string  |  所调用操作的名称。 | 
|  Region  |  string  |  客户端所在的 AWS 区域。仅适用于使用 SigV4[A] 的服务。 | 

 如果您要实现自己的解析器，则永远不需要构造自己的参数实例。SDK 将根据每次请求获取这些值，并将其传递给您的实现。

## 身份验证方案解析工作流程
<a name="auth-scheme-resolution-workflow"></a>

 当您通过 SDK 调用 AWS 服务操作时，在对请求进行序列化后会发生以下一系列操作：

1.  SDK 调用客户端的 `AuthSchemeResolver.ResolveAuthSchemes()` API，根据需要获取输入参数，以获取该操作可能的[选项](https://pkg.go.dev/github.com/aws/smithy-go/auth#Option)列表。

1.  SDK 会遍历该列表，并选择满足以下条件的第一个方案。
   +  客户自己的 `AuthSchemes` 列表中存在具有匹配 ID 的方案 
   +  该方案的身份解析器存在于（非 `nil`）客户端的选项中（通过方案的 `GetIdentityResolver` 方法进行检查，与上述具体身份解析器类型的映射是在内部处理的）（1） 

1.  假设选择了可行的方案，SDK 会调用其 `GetIdentityResolver()` API 来检索调用方的身份。例如，内置的 SigV4 身份验证方案将在内部映射到客户端的 `Credentials` 提供程序。

1.  SDK 调用身份解析器的 `GetIdentity()`（例如 SigV4 的 `aws.CredentialProvider.Retrieve()`）。

1.  SDK 调用端点解析器的 `ResolveEndpoint()` 来查找请求的端点。端点可能包含影响签名过程的其他元数据（例如 S3 Object Lambda 的唯一签名名称）。

1.  SDK 调用身份验证方案的 `Signer()` API 来检索其签署人，并通过其 `SignRequest()` API 使用之前检索的调用方身份对请求进行签名。

 （1）如果 SDK 在列表中遇到匿名选项（ID `smithy.api#noAuth`），则会自动选择该选项，因为没有相应的身份解析器。

## 原生支持的 `AuthScheme`
<a name="natively-supported-authschemes"></a>

 以下身份验证方案由 适用于 Go 的 AWS SDK 原生支持。


|  名称  |  方案 ID  |  身份解析器  |  签署人  |  备注  | 
| --- | --- | --- | --- | --- | 
|  [SigV4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)  |  aws.auth\$1sigv4  |  [aws.CredentialsProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Credentials)  |  [v4.HTTPSigner](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/signer/v4#Signer)  |  大多数 AWS 服务操作的当前默认值。 | 
|  SigV4A  |  aws.auth\$1sigv4a  |  aws.CredentialsProvider  |  不适用  |  目前 SigV4A 的使用受到限制，签署人实现在内部进行。如需了解新的选择加入模块 aws-http-auth（该模块公开了用于签名 HTTP 请求的通用型 API），请参阅此[公告](https://github.com/aws/aws-sdk-go-v2/discussions/2812)。 | 
|  SigV4Express  |  com.amazonaws.s3\$1sigv4express  |  [s3.ExpressCredentialsProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#ExpressCredentialsProvider)  |  v4.HTTPSigner  |  用于 [Express One Zone](https://aws.amazon.com/s3/storage-classes/express-one-zone/)。 | 
|  HTTP Bearer  |  smithy.api\$1httpBearerAuth  |  [smithybearer.TokenProvider](https://pkg.go.dev/github.com/aws/smithy-go/auth/bearer#TokenProvider)  |  [smithybearer.Signer](https://pkg.go.dev/github.com/aws/smithy-go/auth/bearer#Signer)  |  由 [codecatalyst](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/codecatalyst) 使用。 | 
|  匿名  |  smithy.api\$1noAuth  |  不适用  |  不适用  |  不使用身份验证 - 不需要身份，也没有对请求进行签名或身份验证。 | 

### 身份配置
<a name="identity-configuration"></a>

 在适用于 Go 的 AWS SDK 中，身份验证方案的身份组件是在 SDK 客户端 `Options` 中配置的。调用一项操作时，SDK 将自动选取这些组件的值，并将其用于选择的方案。

**注意**  
 出于向后兼容性的考虑，如果未配置身份解析器，SDK 会隐式允许使用匿名身份验证方案。这可通过将客户端 `Options` 上的所有身份解析器设置为 `nil`（sigv4 身份解析器也可设置为 `aws.AnonymousCredentials{}`）来手动实现。

### 签署人配置
<a name="signer-configuration"></a>

 在适用于 Go 的 AWS SDK 中，身份验证方案的签署人组件是在 SDK 客户端 `Options` 中配置的。调用一项操作时，SDK 将自动选取这些组件的值，并将其用于选择的方案。无需进行其他配置。

#### 自定义身份验证方案
<a name="custom-auth-scheme"></a>

 为了定义自定义身份验证方案并对其进行配置以供使用，调用方必须执行以下操作：

1.  定义 [AuthScheme](https://pkg.go.dev/github.com/aws/smithy-go/transport/http#AuthScheme) 实现 

1.  在 SDK 客户端的 `AuthSchemes` 列表中注册该方案 

1.  在适用的情况下，对 SDK 客户端的 `AuthSchemeResolver` 进行检测，以返回带有方案 ID 的身份验证 `Option` 

**警告**  
 以下服务具有独特或自定义的身份验证行为。如需自定义身份验证行为，建议您采用默认实现方式并相应地进行包装：  


|  服务  |  备注  | 
| --- | --- | 
|  S3  |  根据操作输入，有条件地使用 SigV4A 和 SigV4Express。 | 
|  EventBridge  |  根据操作输入，有条件地使用 SigV4A。 | 
|  Cognito  |  某些操作只能匿名执行。 | 
|  SSO  |  某些操作只能匿名执行。 | 
|  STS  |  某些操作只能匿名执行。 | 

# 配置客户端端点
<a name="configure-endpoints"></a>

**警告**  
 端点解析是一个高级 SDK 主题。更改这些设置可能会破坏您的代码。默认设置应适用于生产环境中的大多数用户。

 适用于 Go 的 AWS SDK 提供了配置用于服务的自定义终端节点的功能。大多数情况下，默认配置就足够了。配置自定义端点可以支持其他行为，例如使用服务的预发行版本。

## 自定义
<a name="customization"></a>

 SDK 中有两个“版本”的端点解析配置。
+  v2，于 2023 年第三季度发布，通过以下项进行配置：
  +  `EndpointResolverV2` 
  +  `BaseEndpoint` 
+  v1，与 SDK 一起发布，通过以下项进行配置：
  +  `EndpointResolver` 

 建议使用 v1 端点解析的用户迁移到 v2，以访问更新的与端点相关的服务功能。

## V2：`EndpointResolverV2` \$1 `BaseEndpoint`
<a name="v2-endpointresolverv2--baseendpoint"></a>

 在解析 v2 中，`EndpointResolverV2` 是实现端点解析的最终机制。对于您在 SDK 中发出的每个请求，都会调用解析器的 `ResolveEndpoint` 方法，这是工作流程的一部分。在发出请求时，将**按原样**使用解析器返回的 `Endpoint` 的主机名（但是，操作序列化器仍可附加到 HTTP 路径中）。

 解析 v2 包括一个额外的客户端级别配置 `BaseEndpoint`，用于为您的服务实例指定“基本”主机名。此处设置的值并非最终值 - 进行最终解析时，该值最终会作为参数传递给客户端的 `EndpointResolverV2`（继续阅读，以获取有关 `EndpointResolverV2` 参数的更多信息）。然后，解析器实现有机会检查该值，并可能修改该值以确定最终端点。

 例如，当您使用客户端（在其中指定了 `BaseEndpoint`）对给定存储桶执行 S3 `GetObject` 请求时，如果该存储桶与虚拟主机兼容（假设您尚未在客户端配置中禁用虚拟托管），则默认解析器会将该存储桶注入主机名中。

 实际上，`BaseEndpoint` 很可能用于将您的客户端指向服务的开发或预览实例。

### `EndpointResolverV2` 参数
<a name="endpointresolverv2-parameters"></a>

 每项服务都需要一组特定的输入，这些输入将传递给其解析函数，此函数在每个服务包中定义为 `EndpointParameters`。

 每项服务都包含以下基本参数（这些参数用于为 AWS内部的一般端点解析提供便利）：


|  name  |  类型  |  描述  | 
| --- | --- | --- | 
|  Region  |  string  |  客户 AWS 所在的地区  | 
|  Endpoint  |  string  |  在客户端配置中为 BaseEndpoint 设置的值  | 
|  UseFips  |  bool  |  是否在客户端配置中启用了 FIPS 端点  | 
|  UseDualStack  |  bool  |  是否在客户端配置中启用了双栈端点  | 

 服务可以指定解析所需的其他参数。例如，S3 的 `EndpointParameters` 包括存储桶名称以及几个特定于 S3 的功能设置（例如是否启用虚拟主机寻址）。

 如果您要实现自己的 `EndpointResolverV2`，则永远不需要构造自己的 `EndpointParameters` 实例。SDK 将根据每次请求获取这些值，并将其传递给您的实现。

### 关于 Amazon S3 的说明
<a name="a-note-about-amazon-s3"></a>

 Amazon S3 是一项复杂的服务，其许多功能都是通过复杂的端点自定义建模的，例如存储桶虚拟托管、S3 MRAP 等。

 因此，建议您在 S3 客户端中不要替换 `EndpointResolverV2` 实现。如果需要扩展其解析行为，例如通过向本地开发堆栈发送请求以及其他端点注意事项，建议您包装默认实现，使其作为备用方案回退到默认设置（如以下示例所示）。

### 示例
<a name="examples"></a>

#### 使用 `BaseEndpoint`
<a name="with-baseendpoint"></a>

 以下代码段演示了如何将 S3 客户端指向服务的本地实例，在本示例中，该实例托管在端口 8080 的环回设备上。

```
client := s3.NewFromConfig(cfg, func (o *svc.Options) {
    o.BaseEndpoint = aws.String("https://localhost:8080/")
})
```

#### 使用 `EndpointResolverV2`
<a name="with-endpointresolverv2"></a>

 以下代码段演示了如何使用 `EndpointResolverV2` 将自定义行为注入 S3 的端点解析中。

```
import (
    "context"
    "net/url"

    "github.com/aws/aws-sdk-go-v2/service/s3"
    smithyendpoints "github.com/aws/smithy-go/endpoints"
)

type resolverV2 struct {
    // you could inject additional application context here as well
}

func (*resolverV2) ResolveEndpoint(ctx context.Context, params s3.EndpointParameters) (
        smithyendpoints.Endpoint, error,
    ) {
    if /* input params or caller context indicate we must route somewhere */ {
        u, err := url.Parse("https://custom.service.endpoint/")
        if err != nil {
            return smithyendpoints.Endpoint{}, err
        }
        return smithyendpoints.Endpoint{
            URI: *u,
        }, nil
    }

    // delegate back to the default v2 resolver otherwise
    return s3.NewDefaultEndpointResolverV2().ResolveEndpoint(ctx, params)
}

func main() {
    // load config...

    client := s3.NewFromConfig(cfg, func (o *s3.Options) {
        o.EndpointResolverV2 = &resolverV2{
            // ...
        }
    })
}
```

#### 使用两者
<a name="with-both"></a>

 以下示例程序演示了 `BaseEndpoint` 和 `EndpointResolverV2` 之间的交互。**这是一个高级使用案例：**

```
import (
    "context"
    "fmt"
    "log"
    "net/url"

    "github.com/aws/aws-sdk-go-v2"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
    smithyendpoints "github.com/aws/smithy-go/endpoints"
)

type resolverV2 struct {}

func (*resolverV2) ResolveEndpoint(ctx context.Context, params s3.EndpointParameters) (
        smithyendpoints.Endpoint, error,
    ) {
    // s3.Options.BaseEndpoint is accessible here:
    fmt.Printf("The endpoint provided in config is %s\n", *params.Endpoint)

    // fallback to default
    return s3.NewDefaultEndpointResolverV2().ResolveEndpoint(ctx, params)
}

func main() {
    cfg, err := config.LoadDefaultConfig(context.Background())
    if (err != nil) {
        log.Fatal(err)
    }

    client := s3.NewFromConfig(cfg, func (o *s3.Options) {
        o.BaseEndpoint = aws.String("https://endpoint.dev/")
        o.EndpointResolverV2 = &resolverV2{}
    })

    // ignore the output, this is just for demonstration
    client.ListBuckets(context.Background(), nil)
}
```

 运行时，上面的程序会输出以下内容：

```
The endpoint provided in config is https://endpoint.dev/
```

## V1：`EndpointResolver`
<a name="v1-endpointresolver"></a>

**警告**  
 保留端点解析 v1 以实现向后兼容，并将其与端点解析 v2 中的现代行为隔离开来。仅当调用方设置 `EndpointResolver` 字段时才会使用。  
 使用 v1 很可能会阻止您访问在 v2 解析发布时或之后引入的与端点相关的服务功能。有关如何升级的说明，请参阅“迁移”。

 [EndpointResolver](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#EndpointResolver)可以将 A 配置为为服务客户端提供自定义终端节点解析逻辑。您可以使用自定义端点解析器来覆盖服务对于所有端点的端点解析逻辑，也可以仅覆盖特定的区域端点。如果自定义解析器不希望解析请求的端点，则自定义终端节点解析器可以触发服务的端点解析逻辑回退。 [EndpointResolverWithOptionsFunc](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#EndpointResolverWithOptionsFunc)可以用来轻松包装函数以满足`EndpointResolverWithOptions`接口的需求。

 通过将封装的解析器传递给，`EndpointResolver`可以轻松配置 A [LoadDefaultConfig](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#LoadDefaultConfig)，从而能够在加载凭据时覆盖端点，以及`aws.Config`使用自定义终端节点解析器配置结果。[WithEndpointResolverWithOptions](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#WithEndpointResolverWithOptions)

 端点解析器以字符串形式获得服务和区域，使解析器能够动态驱动其行为。每个服务客户端程序包都有一个导出的 `ServiceID` 常量，可用于确定哪个服务客户端正在调用您的端点解析器。

 端点解析器可以使用 [EndpointNotFoundError](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#EndpointNotFoundError)sentinel 错误值来触发对服务客户端默认解析逻辑的回退解析。这样，您就可以有选择地无缝覆盖一个或多个端点，而不必处理回退逻辑。

 如果您的端点解析器实现返回除 `EndpointNotFoundError` 之外的错误，则端点解析将停止，并且服务操作会向您的应用程序返回错误。

### 示例
<a name="examples-1"></a>

#### 有回退
<a name="with-fallback"></a>

 以下代码段演示了如何为 DynamoDB 覆盖单个服务端点，而其他端点会出现回退行为：

```
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
    if service == dynamodb.ServiceID && region == "us-west-2" {
        return aws.Endpoint{
            PartitionID:   "aws",
            URL:           "https://test.us-west-2.amazonaws.com",
            SigningRegion: "us-west-2",
        }, nil
    }
    // returning EndpointNotFoundError will allow the service to fallback to it's default resolution
    return aws.Endpoint{}, &aws.EndpointNotFoundError{}
})

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver))
```

#### 没有回退
<a name="without-fallback"></a>

 以下代码段演示了如何为 DynamoDB 覆盖单个服务端点，而其他端点不会出现回退行为：

```
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
    if service == dynamodb.ServiceID && region == "us-west-2" {
        return aws.Endpoint{
            PartitionID:   "aws",
            URL:           "https://test.us-west-2.amazonaws.com",
            SigningRegion: "us-west-2",
        }, nil
    }
    return aws.Endpoint{}, fmt.Errorf("unknown endpoint requested")
})

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver))
```

### 不可变端点
<a name="immutable-endpoints"></a>

**警告**  
 将端点设置为不可变可能会使某些服务客户端功能无法正常运行，并可能导致未定义的行为。将端点定义为不可变时应谨慎行事。

 某些服务客户端（例如 Amazon S3）可能会修改解析器为某些服务操作返回的端点。例如，Amazon S3 将通过更改已解析的端点来自动处理[虚拟存储桶寻址](https://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html)。您可以通过将设置为来防止 SDK 更改您的自定义终端节点[HostnameImmutable](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Endpoint.HostnameImmutable)。`true`例如：

```
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
    if service == dynamodb.ServiceID && region == "us-west-2" {
        return aws.Endpoint{
            PartitionID:   "aws",
            URL:           "https://test.us-west-2.amazonaws.com",
            SigningRegion: "us-west-2",
            HostnameImmutable: true,
        }, nil
    }
    return aws.Endpoint{}, fmt.Errorf("unknown endpoint requested")
})

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver))
```

## 迁移
<a name="migration"></a>

 从端点解析的 v1 迁移到 v2 时，应遵循以下一般原则：
+  返回[HostnameImmutable](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Endpoint.HostnameImmutable)设置为`false`的[端点](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Endpoint)大致等同于设置`BaseEndpoint`为 v1 中最初返回的 URL 并保留`EndpointResolverV2`为默认值。
+  返回 HostnameImmutable 设置为的端点大致等同于实现返回 v1 中最初返回`EndpointResolverV2`的 URL 的端点。`true`
  +  主要例外是使用建模端点前缀的操作。关于这方面的说明请见下文。

 下面提供了这些案例的示例。

**警告**  
 V1 不可变端点和 V2 解析在行为上并不相同。例如，仍会为通过 v1 代码返回的不可变端点设置自定义功能（例如 S3 Object Lambda）的签名覆盖，但对于 v2 则不会这样做。

### 关于主机前缀的说明
<a name="note-on-host-prefixes"></a>

 有些操作使用主机前缀进行建模，这些前缀将附加到已解析端点的前面。此行为必须与 ResolveEndpoint V2 的输出配合使用，因此主机前缀仍将应用于该结果。

 您可以通过应用中间件来手动禁用端点主机前缀，请参阅“示例”部分。

### 示例
<a name="examples-2"></a>

#### 可变端点
<a name="mutable-endpoint"></a>

 以下代码示例演示了如何迁移一个返回可修改端点的基本 v1 端点解析器：

```
// v1
client := svc.NewFromConfig(cfg, func (o *svc.Options) {
    o.EndpointResolver = svc.EndpointResolverFromURL("https://custom.endpoint.api/")
})

// v2
client := svc.NewFromConfig(cfg, func (o *svc.Options) {
    // the value of BaseEndpoint is passed to the default EndpointResolverV2
    // implementation, which will handle routing for features such as S3 accelerate,
    // MRAP, etc.
    o.BaseEndpoint = aws.String("https://custom.endpoint.api/")
})
```

#### 不可变端点
<a name="immutable-endpoint"></a>

```
// v1
client := svc.NewFromConfig(cfg, func (o *svc.Options) {
    o.EndpointResolver = svc.EndpointResolverFromURL("https://custom.endpoint.api/", func (e *aws.Endpoint) {
        e.HostnameImmutable = true
    })
})

// v2
import (
    smithyendpoints "github.com/aws/smithy-go/endpoints"
)

type staticResolver struct {}

func (*staticResolver) ResolveEndpoint(ctx context.Context, params svc.EndpointParameters) (
        smithyendpoints.Endpoint, error,
    ) {
    // This value will be used as-is when making the request.
    u, err := url.Parse("https://custom.endpoint.api/")
    if err != nil {
        return smithyendpoints.Endpoint{}, err
    }
    return smithyendpoints.Endpoint{
        URI: *u,
    }, nil
}

client := svc.NewFromConfig(cfg, func (o *svc.Options) {
    o.EndpointResolverV2 = &staticResolver{}
})
```

#### 禁用主机前缀
<a name="disable-host-prefix"></a>

```
import (
    "context"
    "fmt"
    "net/url"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/<service>"
    smithyendpoints "github.com/aws/smithy-go/endpoints"
    "github.com/aws/smithy-go/middleware"
    smithyhttp "github.com/aws/smithy-go/transport/http"
)

// disableEndpointPrefix applies the flag that will prevent any
// operation-specific host prefix from being applied
type disableEndpointPrefix struct{}

func (disableEndpointPrefix) ID() string { return "disableEndpointPrefix" }

func (disableEndpointPrefix) HandleInitialize(
    ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
) (middleware.InitializeOutput, middleware.Metadata, error) {
    ctx = smithyhttp.SetHostnameImmutable(ctx, true)
    return next.HandleInitialize(ctx, in)
}

func addDisableEndpointPrefix(o *<service>.Options) {
    o.APIOptions = append(o.APIOptions, (func(stack *middleware.Stack) error {
        return stack.Initialize.Add(disableEndpointPrefix{}, middleware.After)
    }))
}

type staticResolver struct{}

func (staticResolver) ResolveEndpoint(ctx context.Context, params <service>.EndpointParameters) (
    smithyendpoints.Endpoint, error,
) {
    u, err := url.Parse("https://custom.endpoint.api/")
    if err != nil {
        return smithyendpoints.Endpoint{}, err
    }

    return smithyendpoints.Endpoint{URI: *u}, nil
}


func main() {
    cfg, err := config.LoadDefaultConfig(context.Background())
    if err != nil {
        panic(err)
    }

    svc := <service>.NewFromConfig(cfg, func(o *<service>.Options) {
        o.EndpointResolverV2 = staticResolver{}
    })

    _, err = svc.<Operation>(context.Background(), &<service>.<OperationInput>{ /* ... */ },
        addDisableEndpointPrefix)
    if err != nil {
        panic(err)
    }
}
```

# 自定义 HTTP 客户端
<a name="configure-http"></a>

 适用于 Go 的 AWS SDK 使用具有默认配置值的默认 HTTP 客户端。尽管您可以更改其中的一些配置值，但对于在具有高吞吐量和低延迟要求的环境中使用适用于 Go 的 AWS SDK 的客户而言，默认的 HTTP 客户端和传输并未充分配置。有关更多信息，请参阅[常见问题](faq-gosdk.md)，因为配置建议因具体工作负载而异。本节介绍如何配置自定义 HTTP 客户端，以及如何使用该客户端创建适用于 Go 的 AWS SDK 调用。

 为了帮助您创建自定义 HTTP 客户端，本节介绍如何使用 [NewBuildableClient](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/transport/http#NewBuildableClient) 配置自定义设置，以及如何将该客户端与适用于 Go 的 AWS SDK 服务客户端结合使用。

 我们来确定要自定义的内容。

## 在配置加载期间覆盖
<a name="overriding-during-configuration-loading"></a>

 调用 [LoadDefaultConfig](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#LoadDefaultConfig) 时，可以提供自定义 HTTP 客户端，方法是使用 [WithHTTPClient](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#WithHTTP) 包装客户端并将结果值传递给 `LoadDefaultConfig`。例如，传递 `customClient` 作为我们的客户端：

```
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithHTTPClient(customClient))
```

## 超时
<a name="timeout"></a>

 可以为 `BuildableHTTPClient` 配置请求超时限制。此超时包括进行连接、处理任何重定向和读取完整响应正文所需的时间。例如，修改客户端超时：

```
import "github.com/aws/aws-sdk-go-v2/aws/transport/http"

// ...

httpClient := http.NewBuildableClient().WithTimeout(time.Second*5)
```

## 拨号器
<a name="dialer"></a>

 `BuildableHTTPClient` 提供了一种生成器机制，用于使用修改后的[拨号器](https://golang.org/pkg/net/#Dialer)选项来构造客户端。下面的示例演示了如何配置客户端 `Dialer` 设置。

```
import awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
import "net"

// ...

httpClient := awshttp.NewBuildableClient().WithDialerOptions(func(d *net.Dialer) {
    d.KeepAlive = -1
    d.Timeout = time.Millisecond*500
})
```

### 设置
<a name="settings"></a>

#### Dialer.KeepAlive
<a name="dialerkeepalive"></a>

 此设置表示活动网络连接的“保持连接”时间。

 设置为负值可禁用“保持连接”。

 如果协议和操作系统支持，则设置为 **0** 可启用“保持连接”。

 不支持“保持连接”的网络协议或操作系统会忽略此字段。默认情况下，TCP 启用“保持连接”。

 请参阅 [https://golang.org/pkg/net/\$1Dialer.KeepAlive](https://golang.org/pkg/net/#Dialer.KeepAlive) 

 将 `KeepAlive` 设置为 **time.Duration**。

#### Dialer.Timeout
<a name="dialertimeout"></a>

 此设置表示拨号等待建立连接的最长时间。

 默认为 30 秒。

 请参阅 [https://golang.org/pkg/net/\$1Dialer.Timeout](https://golang.org/pkg/net/#Dialer.Timeout) 

 将 `Timeout` 设置为 **time.Duration**。

## 传输
<a name="transport"></a>

 `BuildableHTTPClient` 提供了一种生成器机制，用于使用修改后的[传输](https://golang.org/pkg/net/http#Transport)选项来构造客户端。

### 配置代理
<a name="configuring-a-proxy"></a>

 如果无法直接连接到互联网，可以使用 Go 支持的环境变量（`HTTP_PROXY`/`HTTPS_PROXY`）或创建自定义 HTTP 客户端来配置代理。以下示例将客户端配置为使用 `PROXY_URL` 作为代理端点：

```
import awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
import "net/http"

// ...

httpClient := awshttp.NewBuildableClient().WithTransportOptions(func(tr *http.Transport) {
    proxyURL, err := url.Parse("PROXY_URL")
    if err != nil {
        log.Fatal(err)
    }
    tr.Proxy = http.ProxyURL(proxyURL)
})
```

### 其他设置
<a name="other-settings"></a>

 以下是一些其他 `Transport` 设置，可以修改这些设置以调整 HTTP 客户端。此处未描述的任何其他设置均可在[传输](https://golang.org/pkg/net/http/#Transport)类型文档中找到。可按以下示例所示应用这些设置：

```
import awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
import "net/http"

// ...

httpClient := awshttp.NewBuildableClient().WithTransportOptions(func(tr *http.Transport) {
    tr.ExpectContinueTimeout = 0
    tr.MaxIdleConns = 10
})
```

#### Transport.ExpectContinueTimeout
<a name="transportexpectcontinuetimeout"></a>

 如果请求有“Expect: 100-continue”标头，则此设置表示在完全写入请求标头后等待服务器初始响应标头的最长时间。该时间不包括发送请求标头所花费的时间。此超时结束后，HTTP 客户端会发送其有效载荷。

 默认值 1 秒。

 设置为 **0** 表示没有超时，无需等待即可发送请求有效载荷。一个使用案例是，当代理或第三方服务遇到问题时，它们会占用一个会话，这与后文示例函数中使用 Amazon S3 的情况类似。

 请参阅 [https://golang.org/pkg/net/http/\$1Transport.ExpectContinueTimeout](https://golang.org/pkg/net/http/#Transport.ExpectContinueTimeout) 

 将 `ExpectContinue` 设置为 **time.Duration**。

#### Transport.IdleConnTimeout
<a name="transportidleconntimeout"></a>

 此设置表示在 HTTP 请求之间保持空闲网络连接处于活动状态的最长时间。

 设置为 **0** 表示没有限制。

 请参阅 [https://golang.org/pkg/net/http/\$1Transport.IdleConnTimeout](https://golang.org/pkg/net/http/#Transport.IdleConnTimeout) 

 将 `IdleConnTimeout` 设置为 **time.Duration**。

#### Transport.MaxIdleConns
<a name="transportmaxidleconns"></a>

 此设置表示所有主机上空闲（保持连接）连接的最大数量。增大此值的一个使用案例是，您在短时间内发现来自相同客户端的许多连接 

 **0** 表示没有限制。

 请参阅 [https://golang.org/pkg/net/http/\$1Transport.MaxIdleConns](https://golang.org/pkg/net/http/#Transport.MaxIdleConns) 

 将 `MaxIdleConns` 设置为 **int**。

#### Transport.MaxIdleConnsPerHost
<a name="transportmaxidleconnsperhost"></a>

 此设置表示每台主机要保留的空闲（保持连接）连接的最大数量。增大此值的一个使用案例是，您在短时间内发现来自相同客户端的许多连接 

 默认情况下，每台主机有两个空闲连接。

 设置为 **0** 将使用 DefaultMaxIdleConnsPerHost（2）。

 请参阅 [https://golang.org/pkg/net/http/\$1Transport.MaxIdleConnsPerHost](https://golang.org/pkg/net/http/#Transport.MaxIdleConnsPerHost) 

 将 `MaxIdleConnsPerHost` 设置为 **int**。

#### Transport.ResponseHeaderTimeout
<a name="transportresponseheadertimeout"></a>

 此设置表示等待客户端读取响应标头的最长时间。

 如果客户端无法在这段时间内读取响应的标头，则请求将失败并显示超时错误。

 使用长时间运行的 Lambda 函数时请谨慎设置此值，因为在 Lambda 函数完成或超时之前，该操作不会返回任何响应标头。但是，您仍然可以在 \$1\$1 InvokeAsync\$1\$1 API 操作中使用此选项。

 默认为没有超时；将会一直等待。

 请参阅 [https://golang.org/pkg/net/http/\$1Transport.ResponseHeaderTimeout](https://golang.org/pkg/net/http/#Transport.ResponseHeaderTimeout) 

 将 `ResponseHeaderTimeout` 设置为 **time.Duration**。

#### Transport.TLSHandshakeTimeout
<a name="transporttlshandshaketimeout"></a>

 此设置表示等待 TLS 握手完成的最长时间。

 默认为 10 秒。

 零表示没有超时。

 请参阅 [https://golang.org/pkg/net/http/\$1Transport.TLSHandshakeTimeout](https://golang.org/pkg/net/http/#Transport.TLSHandshakeTimeout) 

 将 `TLSHandshakeTimeout` 设置为 **time.Duration**。

# HTTP 拦截器
<a name="interceptors"></a>

 您可以使用拦截器介入 API 请求和响应的执行过程。拦截器是一种开放式机制，在这种机制中，SDK 会调用您编写的代码，以将行为注入到请求/响应生命周期中。这样，您便可修改正在进行的请求、调试请求处理、查看异常等。

## 拦截器与中间件
<a name="interceptors-vs-middleware"></a>

 适用于 Go 的 AWS SDK v2 提供了拦截器和中间件，用于自定义请求处理。虽然两者的作用相似，但它们针对的受众和应用场景却有所不同：
+  **拦截器**专为想要使用简单的、以 HTTP 为中心的 API 对请求/响应处理进行自定义的 SDK 用户而设计。它们在请求生命周期中提供特定的钩子点，并直接处理 HTTP 请求和响应。
+  **中间件**是一种更为高级且与传输方式无关的系统，主要由 SDK 在内部使用。虽然中间件功能强大，但需要更深入地了解 SDK 内部结构，并且涉及更复杂的接口。

 在常见使用案例中，拦截器相较于中间件的主要优势如下：
+  **以 HTTP 为中心**：拦截器直接处理 HTTP 请求和响应，无需像中间件那样进行传输类型检查。
+  **更简单的接口**：每个拦截器钩子都有一个特定的、有针对性的接口，而不是通用的中间件模式。
+  **更清晰的执行模型**：拦截器在请求生命周期中定义明确的时刻执行，无需了解中间件堆栈排序。

**注意**  
 拦截器在现有的中间件系统上构建而成，因此两者可以在同一个应用程序中共存。中间件仍可用于需要与传输无关的行为或复杂堆栈操作的高级使用案例。

## 可用拦截器钩子
<a name="interceptor-hooks"></a>

 适用于 Go 的 AWS SDK v2 在请求生命周期的各个阶段都提供拦截器钩子。每个钩子都对应一个您可以实现的特定接口：
+  `BeforeExecution` - 操作执行期间调用的第一个钩子 
+  `BeforeSerialization` - 在输入消息序列化为传输请求之前 
+  `AfterSerialization` - 在输入消息序列化为传输请求之后 
+  `BeforeRetryLoop` - 在进入重试循环之前 
+  `BeforeAttempt` - 重试循环内调用的第一个钩子 
+  `BeforeSigning` - 在签署运输请求之前 
+  `AfterSigning` - 在签署运输请求之后 
+  `BeforeTransmit` - 在发送传输请求之前 
+  `AfterTransmit` - 在收到运输响应之后 
+  `BeforeDeserialization` - 在传输响应被反序列化之前 
+  `AfterDeserialization` - 在解组传输响应之后 
+  `AfterAttempt` - 重试循环内调用的最后一个钩子 
+  `AfterExecution` - 操作执行期间调用的最后一个钩子 

 您可以在单个拦截器中实现多个接口，以介入请求生命周期的多个阶段。

## 拦截器注册
<a name="interceptor-registration"></a>

 构造服务客户端或覆盖特定操作的配置时，可以注册拦截器。注册方式会有所不同，具体取决于您希望拦截器应用于客户端的所有操作，还是仅应用于特定操作。

 通过拦截器注册表来管理拦截器，该注册表提供了添加和删除拦截器的方法。以下示例显示了一个简单的拦截器，该拦截器在签名过程之前向传出的请求添加 AWS X-Ray 跟踪 ID 标头：

```
type recursionDetection struct{}

func (recursionDetection) BeforeSigning(ctx context.Context, in *smithyhttp.InterceptorContext) error {
    if traceID := os.Getenv("_X_AMZN_TRACE_ID"); traceID != "" {
        in.Request.Header.Set("X-Amzn-Trace-Id", traceID)
    }
    return nil
}

// use it on the client
svc := s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.Interceptors.AddBeforeSigning(recursionDetection{})
})
```

 拦截器注册表已添加到客户端选项中，从而能够按操作来配置拦截器：

```
// ... or use it per-operation
s3.ListBuckets(context.Background(), &s3.ListBucketsInput{
}, func(o *s3.Options) {
   o.Interceptors.AddBeforeSigning(recursionDetection{})
})
```

## 全局拦截器配置
<a name="interceptor-global-config"></a>

 您还可以使用 `config.LoadDefaultConfig` 函数在全局注册拦截器，每种拦截器类型都有相应的 `With*` 选项。这会将拦截器应用于根据该配置创建的所有 AWS 服务客户端：

```
type myExecutionInterceptor struct{}

func (*myExecutionInterceptor) AfterExecution(ctx context.Context, in *smithyhttp.InterceptorContext) error {
    // Add your custom logic here
    return nil
}

cfg, err := config.LoadDefaultConfig(context.Background(),
    config.WithAfterExecution(&myExecutionInterceptor{}))
if err != nil {
    panic(err)
}

// every service client created from the above config
// will include this interceptor
svc := s3.NewFromConfig(cfg)
```

# 日志记录
<a name="configure-logging"></a>

 适用于 Go 的 AWS SDK 具有日志记录功能，使您的应用程序能够提供调试信息来调试和诊断请求问题或请求失败。[Logger](https://pkg.go.dev/github.com/aws/smithy-go/logging#Logger) 接口和 [ClientLogMode](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#ClientLogMode) 是可用于确定客户端记录方式和记录内容的主要组件。

## 记录器
<a name="logger"></a>

 使用 [LoadDefaultConfig](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#LoadDefaultConfig) 构造 [Config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Config) 时，默认 `Logger` 配置为向进程的标准错误（stderr）发送日志消息。通过用 [config.WithLogger](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#WithLogger) 进行包装，可以将满足 [Logger](https://pkg.go.dev/github.com/aws/smithy-go/logging#Logger) 接口的自定义记录器作为参数传递给 `LoadDefaultConfig`。

 例如，将我们的客户端配置为使用我们的 `applicationLogger`：

```
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithLogger(applicationLogger))
```

 现在，使用构造的 `aws.Config` 配置的客户端将向 `applicationLogger` 发送日志消息。

### 上下文感知记录器
<a name="context-aware-loggers"></a>

 记录器实现可以实现可选的 [ContextLogger](https://pkg.go.dev/github.com/aws/smithy-go/logging#ContextLogger) 接口。实现此接口的记录器将在当前上下文中调用其 `WithContext` 方法。这允许您的日志记录实现返回一个新 `Logger`，它可以根据上下文中存在的值写入额外的日志元数据。

## ClientLogMode
<a name="clientlogmode"></a>

 默认情况下，服务客户端不会生成日志消息。要将客户端配置为出于调试目的发送日志消息，请使用 `Config` 上的 [ClientLogMode](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#ClientLogMode) 成员。`ClientLogMode` 可设置为启用以下内容的调试消息：
+  签名版本 4（SigV4）签名 
+  请求重试 
+  HTTP 请求 
+  HTTP 响应 

 例如，启用 HTTP 请求和重试的日志记录：

```
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithClientLogMode(aws.LogRetries | aws.LogRequest))
```

 有关可用的不同客户端日志模式，请参阅 [ClientLogMode](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#ClientLogMode)。

# 跟踪和指标
<a name="configure-observability"></a>

 用于记录 S 适用于 Go 的 AWS SDK DK 操作的跟踪跨度和客户端指标。默认情况下，客户端对跟踪和指标都使用无操作实现，这意味着除非您配置提供程序，否则不会收集任何数据。

 服务客户端有两个可观察性配置选项：
+  [TracerProvider](https://pkg.go.dev/github.com/aws/smithy-go/tracing#TracerProvider)— 用于创建追踪器和记录客户跟踪跨度的入口点。
+  [MeterProvider](https://pkg.go.dev/github.com/aws/smithy-go/metrics#MeterProvider)— 创建仪表和记录客户端指标的入口点。

 虽然受到 OpenTelemetry (OTel) 规范的启发，但 APIs 它们是在中独立定义的`smithy-go`。SDK 提供了适配器模块，用于将具体的 OTel SDK 实现与 SDK 的提供者接口连接起来。

## 跟踪
<a name="configure-tracing"></a>

 使用 s [mithyoteltr](https://pkg.go.dev/github.com/aws/smithy-go/tracing/smithyoteltracing) acing 适配器模块将 OTel `trace.TracerProvider`连接到服务客户端。

 以下示例显示了如何为 Amazon S3 客户端配置跟踪：

```
import (
    "github.com/aws/aws-sdk-go-v2/service/s3"
    "github.com/aws/smithy-go/tracing/smithyoteltracing"
    "go.opentelemetry.io/otel/trace"
)

// provider is an OTel trace.TracerProvider that you have configured.
var provider trace.TracerProvider

svc := s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.TracerProvider = smithyoteltracing.Adapt(provider)
})
```

 SDK 操作采用跨度层次结构进行检测，该层次结构涵盖了操作生命周期的高级组件，例如请求序列化、签名和重试循环。

## 指标
<a name="configure-metrics"></a>

 使用 s [mithyotelmetrics](https://pkg.go.dev/github.com/aws/smithy-go/metrics/smithyotelmetrics) 适配器模块将 OTel `metric.MeterProvider`连接到服务客户端。

 以下示例说明如何为 Amazon S3 客户端配置指标：

```
import (
    "github.com/aws/aws-sdk-go-v2/service/s3"
    "github.com/aws/smithy-go/metrics/smithyotelmetrics"
    "go.opentelemetry.io/otel/metric"
)

// provider is an OTel metric.MeterProvider that you have configured.
var provider metric.MeterProvider

svc := s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.MeterProvider = smithyotelmetrics.Adapt(provider)
})
```

### 受支持的指标
<a name="supported-metrics"></a>

 SDK 客户端收集以下指标：


| 指标名称 | 单位 | Type | 说明 | 
| --- | --- | --- | --- | 
| client.call.duration | s | 直方图 | 总呼叫时长，包括重试次数、发送或接收请求和响应正文的时间。 | 
| client.call.attempts | \$1attempt\$1 | MonotonicCounter | 单个操作的尝试次数。 | 
| client.call.errors | \$1error\$1 | MonotonicCounter | 某项操作的错误数。 | 
| client.call.attempt\$1duration | s | 直方图 | 连接到服务、发送请求以及取回 HTTP 状态码和标头的时间（包括等待发送的排队时间）。 | 
| client.call.resolve\$1endpoint\$1duration | s | 直方图 | 为请求解析终端节点（终端节点解析器，不是 DNS）的时间。 | 
| client.call.deserialization\$1duration | s | 直方图 | 是时候反序列化消息正文了。 | 
| client.call.auth.signing\$1duration | s | 直方图 | 签署请求的时间。 | 
| client.call.auth.resolve\$1identity\$1duration | s | 直方图 | 从身份提供者那里获取身份（AWS 凭证、持有者令牌等）的时间。 | 

 在适用的情况下，每个指标都包含以下属性（维度）：
+ `rpc.service`— 服务名称。
+ `rpc.method`— 操作名称。
+ `exception.type`— 错误类型（包含在中`client.call.errors`）。
+ `auth.scheme_id`— 身份验证方案（包含在与身份验证相关的指标中）。

### HTTP 客户端指标
<a name="http-client-metrics"></a>

 SDK 的 HTTP 客户端收集以下与底层 HTTP 连接生命周期相关的其他指标：


| 指标名称 | 单位 | Type | 说明 | 
| --- | --- | --- | --- | 
| client.http.connections.acquire\$1duration | s | 直方图 | 请求获取连接所花费的时间。 | 
| client.http.connections.dns\$1lookup\$1duration | s | 直方图 | 执行 DNS 查询所花费的时间。 | 
| client.http.connections.tls\$1handshake\$1duration | s | 直方图 | 执行 TLS 握手所需的时间。 | 
| client.http.connections.usage | \$1连接\$1 | UpDownCounter | 池中连接的当前状态。使用值为idle或的state维度acquired。 | 
| client.http.do\$1request\$1duration | s | 直方图 | 执行 HTTP 请求所花费的总时间。 | 
| client.http.time\$1to\$1first\$1byte | s | 直方图 | 从发送请求到收到第一个响应字节的时间。 | 

# 重试和超时
<a name="configure-retries-timeouts"></a>

 适用于 Go 的 AWS SDK 使您可以配置向 HTTP 服务发出的请求的重试行为。默认情况下，服务客户端使用 [retry.Standard](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#Standard) 作为其默认重试器。如果默认配置或行为不符合应用程序要求，可以调整重试器配置或提供自己的重试器实现。

 适用于 Go 的 AWS SDK 提供了一个 [AWS.retryer](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Retryer) 接口，该接口定义了实现重试实现所需的方法集。[该软件开发工具包提供了两种重试实现方式：[retry.](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#Standard) Standard 和 aws。 NoOpRetryer](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#NoOpRetryer)。

## 标准重试器
<a name="standard-retryer"></a>

 [retry.Standard](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#Standard) 重试器是 SDK 客户端使用的默认 `aws.Retryer` 实现。标准重试器是一种速率受限的重试器，其最大尝试次数可配置，并能够调整请求回退策略。

 下表定义了此重试器的默认值：


| 属性 | 默认 | 
| --- | --- | 
|  最大尝试次数  |  3  | 
|  最大回退延迟  |  20 秒  | 

 如果在调用请求时发生可重试错误，标准重试器将使用其提供的配置来延迟请求，并随后重试请求。重试会增加请求的总体延迟，如果默认配置不符合应用程序要求，则必须配置重试器。

 有关标准重试器实现将哪些错误视为可重试错误的详细信息，请参阅 [retry](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry) 程序包文档。

## NopRetryer
<a name="nopretryer"></a>

 那个 a [ws。 NopRetryer](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#NopRetryer)如果您希望禁用所有重试尝试，则会提供此`aws.Retryer`实现。调用服务客户端操作时，此重试器只允许尝试执行一次请求，并且由此产生的任何错误都将返回给调用应用程序。

## 自定义行为
<a name="customizing-behavior"></a>

 SDK 提供一组帮助程序实用程序（用于包装 `aws.Retryer` 实现），并返回提供的重试器（用所需重试行为进行了包装）。您可以根据应用程序要求，覆盖所有客户端、每个客户端或每项操作的默认重试器。要查看演示如何执行此操作的其他示例，请参阅 [retry](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry) 程序包文档示例。

**警告**  
 如果使用 `config.WithRetryer` 指定全局 `aws.Retryer` 实现，则必须确保每次调用都返回一个新的 `aws.Retryer` 实例。这将确保不会跨所有服务客户端创建一个全局重试令牌存储桶。

### 限制最大尝试次数
<a name="limiting-the-max-number-of-attempts"></a>

 你使用[重试。 AddWithMaxAttempts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#AddWithMaxAttempts)封装`aws.Retryer`实现以将最大尝试次数设置为所需值。

**警告**  
 使用值为零的 `retry.AddWithMaxAttempts` 将允许 SDK 重试所有可重试错误，直到请求成功，或直到返回不可重试错误。**允许 SDK 无限次重试可能会导致工作负载失控和计费周期过长。**

```
import "context"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"

// ...

// MaxAttempts will be infinite (will retry indefinitely)
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRetryer(func() aws.Retryer {
    return retry.AddWithMaxAttempts(retry.NewStandard(), 0)
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

 请注意，使用 MaxAttempts 直接设置的功能选项实例化重试器的行为会略有不同。更具体地说，如果将值设置为小于或等于零，重试器将使用默认的最大尝试次数（即 3 次），而不是无限次重试：

```
import "context"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"

// ...

// MaxAttempts will default to 3
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRetryer(func() aws.Retryer {
    return retry.NewStandard(func(o *retry.StandardOptions) {
        o.MaxAttempts = 0
    })
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

### 限制最大回退延迟
<a name="limiting-the-max-back-off-delay"></a>

 你使用[重试。 AddWithMaxBackoffDelay](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#AddWithMaxBackoffDelay)封装`aws.Retryer`实现并限制在重试失败的请求之间允许的最大退出延迟。

 例如，您可以使用以下代码来包装标准客户端重试器，使其所需的最大延迟为五秒：

```
import "context"
import "time"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
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(), config.WithRetryer(func() aws.Retryer {
    return retry.AddWithMaxBackoffDelay(retry.NewStandard(), time.Second*5)
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

### 重试其他 API 错误代码
<a name="retry-additional-api-error-codes"></a>

 你使用[重试。 AddWithErrorCodes](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#AddWithErrorCodes)封装`aws.Retryer`实现并包含其他 API 错误代码，这些错误代码应被视为可重试。

 例如，您可以使用以下代码来包装标准客户端重试器，以将 Amazon S3 `NoSuchBucketException` 异常包括在可重试的范围之内。

```
import "context"
import "time"
import "github.com/aws/aws-sdk-go-v2/aws/retry"
import "github.com/aws/aws-sdk-go-v2/config"
import "github.com/aws/aws-sdk-go-v2/service/s3"
import "github.com/aws/aws-sdk-go-v2/service/s3/types"

// ...

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRetryer(func() aws.Retryer {
    return retry.AddWithErrorCodes(retry.NewStandard(), (*types.NoSuchBucketException)(nil).ErrorCode())
}))
if err != nil {
    return err
}

client := s3.NewFromConfig(cfg)
```

### 客户端速率限制
<a name="client-side-rate-limiting"></a>

 在标准重试策略中 适用于 Go 的 AWS SDK 引入了一种新的客户端速率限制机制，以适应现代的行为。 SDKs[这是由重试者选项上的[RateLimiter](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#RateLimiter)字段控制的行为。](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/retry#StandardOptions)

 作为具有设定容量的令牌存储桶 RateLimiter 运行，其中操作尝试失败会消耗令牌。如果重试尝试消耗的令牌多于可用令牌，则会导致操作失败。[QuotaExceededError](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/ratelimit#QuotaExceededError)

 默认实现的参数化如下（如何修改每种设置）：
+  容量为 500（ StandardOptions 使用时设置 RateLimiter 的值 [NewTokenRateLimit](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/ratelimit#NewTokenRateLimit)） 
+  超时导致的重试消耗 10 个代币（设置为 RetryTimeoutCost 开启 StandardOptions） 
+  由其他错误导致的重试消耗 5 个代币（设置为 RetryCost开启 StandardOptions） 
+  第一次尝试成功的操作会添加 1 个令牌（设置为 “ NoRetryIncrement 启 StandardOptions用”） 
  +  第二次或以后的尝试成功的操作不会重新增加任何令牌 

 如果您发现默认行为不符合应用程序的需求，可以使用 [ratelimit.None](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/ratelimit#pkg-variables) 将其禁用。

#### 示例：修改后的速率限制器
<a name="example-modified-rate-limiter"></a>

```
import (
    "context"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/aws/ratelimit"
    "github.com/aws/aws-sdk-go-v2/aws/retry"
    "github.com/aws/aws-sdk-go-v2/config"
)

// ...

cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRetryer(func() aws.Retryer {
    return retry.NewStandard(func(o *retry.StandardOptions) {
        // Makes the rate limiter more permissive in general. These values are
        // arbitrary for demonstration and may not suit your specific
        // application's needs.
        o.RateLimiter = ratelimit.NewTokenRateLimit(1000)
        o.RetryCost = 1
        o.RetryTimeoutCost = 3
        o.NoRetryIncrement = 10
    })
}))
```

#### 示例：使用 ratelimit.None 没有速率限制
<a name="example-no-rate-limit-using-ratelimitnone"></a>

```
import (
    "context"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/aws/ratelimit"
    "github.com/aws/aws-sdk-go-v2/aws/retry"
    "github.com/aws/aws-sdk-go-v2/config"
)

// ...

cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRetryer(func() aws.Retryer {
    return retry.NewStandard(func(o *retry.StandardOptions) {
        o.RateLimiter = ratelimit.None
    })
}))
```

## 超时
<a name="timeouts"></a>

 调用服务客户端操作时，您可以使用 [context](https://golang.org/pkg/context/) 程序包来设置超时或截止日期。使用[上下文。 WithDeadline](https://golang.org/pkg/context/#WithDeadline)封装您的应用程序上下文并将截止日期设置为必须完成调用操作的特定时间。在特定`time.Duration`使用[上下文之后设置超时。 WithTimeout](https://golang.org/pkg/context/#WithTimeout)。调用服务 API 时，SDK 会将提供的 `context.Context` 传递给 HTTP 传输客户端。如果调用操作时，传递给 SDK 的上下文已取消或变成已取消状态，SDK 将不会进一步重试请求，并将返回到调用应用程序。如果提供给 SDK 的上下文变成已取消状态，则必须在应用程序中适当处理上下文取消。

### 设置超时值
<a name="setting-a-timeout"></a>

 以下示例代码演示了如何为服务客户端操作设置超时值。

```
import "context"
import "time"

// ...

ctx := context.TODO() // or appropriate context.Context value for your application

client := s3.NewFromConfig(cfg)

// create a new context from the previous ctx with a timeout, e.g. 5 seconds
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()

resp, err := client.GetObject(ctx, &s3.GetObjectInput{
    // input parameters
})
if err != nil {
    // handle error
}
```