

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 遷移至 適用於 Go 的 AWS SDK v2
<a name="migrate-gosdk"></a>

## 最低 Go 版本
<a name="minimum-go-version"></a>

 適用於 Go 的 AWS SDK 需要 Go 1.23 的最低版本。您可以在下載[https://go.dev/dl/](https://go.dev/dl/)頁面上下載最新版本的 Go。如需每個 Go 版本版本的詳細資訊，以及升級所需的相關資訊，請參閱[發行歷史記錄](https://go.dev/doc/devel/release)。

## 模組化
<a name="modularization"></a>

 適用於 Go 的 AWS SDK 已更新，以利用 Go 模組成為 Go 1.13 的預設開發模式。軟體開發套件提供的許多套件已模組化，並分別獨立進行版本化和發行。此變更可改善應用程式相依性建模，並讓 SDK 提供遵循 Go 模組版本控制策略的新功能。

 以下是 SDK 提供的一些 Go 模組：


|  模組  |  Description  | 
| --- | --- | 
|  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 的服務用戶端和更高層級的公用程式模組會巢狀在下列匯入路徑下：


|  匯入根目錄  |  Description  | 
| --- | --- | 
|  github.com/aws/aws-sdk-go-v2/service/  |  服務用戶端模組  | 
|  github.com/aws/aws-sdk-go-v2/feature/  |  Amazon S3 Transfer Manager 等服務的高階公用程式  | 

## 組態載入
<a name="configuration-loading"></a>

 [工作階段](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/)套件和相關聯的功能會取代為組態套件提供的簡化[組態](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config)系統。`config` 套件是單獨的 Go 模組，可以透過 將 包含在應用程式的相依性中`go get`。

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

 session[.New](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/#New)、[session.NewSession](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/#NewSession)、[NewSessionWithOptions](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/#NewSessionWithOptions) 和 [session.Must](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/#Must) 必須遷移至 [config.LoadDefaultConfig](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#LoadDefaultConfig)。

 `config` 套件提供數個協助程式函數，可協助以程式設計方式覆寫共用組態載入。這些函數名稱的字首為 ，`With`後面接著其覆寫的選項。讓我們來看看如何遷移`session`套件用量的一些範例。

 如需載入共用組態的詳細資訊，請參閱 [設定軟體開發套件](configure-gosdk.md)。

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

#### 從 NewSession 遷移至 LoadDefaultConfig
<a name="migrating-from-newsession-to-loaddefaultconfig"></a>

 下列範例顯示 在沒有其他引數參數`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 遷移
<a name="migrating-from-newsession-with-awsconfig-options"></a>

 此範例示範如何在組態載入期間遷移覆寫`aws.Config`值。可以提供一或多個`config.With*`協助程式函數給 `config.LoadDefaultConfig`，以覆寫載入的組態值。在此範例中， AWS 區域會覆寫為`us-west-2`使用 [config.WithRegion](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#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 遷移
<a name="migrating-from-newsessionwithoptions"></a>

 此範例示範如何在組態載入期間遷移覆寫值。可以提供零或多個`config.With*`協助程式函數給 `config.LoadDefaultConfig`，以覆寫載入的組態值。在此範例中，我們會示範如何覆寫載入 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`
<a name="mocking-and-iface"></a>

 其中的`*iface`套件和界面 （例如 [s3iface.S3API](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/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 進行單位測試](unit-testing.md)。

## 登入資料和登入資料提供者
<a name="credentials--credential-providers"></a>

 [aws/credentials](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/) 套件和相關聯的登入資料提供者已重新定位至[登入資料](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials)套件位置。`credentials` 套件是您使用 擷取的 Go 模組`go get`。

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

 適用於 Go 的 AWS SDK v2 版本會更新 AWS 登入資料提供者，以提供一致的介面來擷取 AWS 登入資料。每個提供者都會實作 [aws.CredentialsProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#CredentialsProvider) 介面，定義傳回類似 適用於 Go 的 AWS SDK v1 [登入資料.Value ](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/#Value)類型的 `(aws.Credentials, error)`. [aws.Credentials](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Credentials) `Retrieve`的方法。

 您必須使用 [aws.CredentialsCache](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#CredentialsCache) 包裝`aws.CredentialsProvider`物件，以允許發生登入資料快取。您可以使用 [NewCredentialsCache](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#NewCredentialsCache) 建構`aws.CredentialsCache`物件。根據預設，由 設定的登入資料`config.LoadDefaultConfig`會包裝在 中`aws.CredentialsCache`。

 下表列出登入資料提供者從 適用於 Go 的 AWS SDK v1 到 v2 AWS 的位置變更。


|  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  | 

### 靜態登入資料
<a name="static-credentials"></a>

 使用 [credentials.NewStaticCredentials](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials//#NewStaticCredentials) 以程式設計方式建構靜態登入資料的應用程式必須使用 [credentials.NewStaticCredentialsProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials#NewStaticCredentialsProvider)。

#### 範例
<a name="example"></a>

```
// 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 角色登入資料
<a name="ec2-iam-role-credentials"></a>

 您必須遷移 [NewCredentials](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/ec2rolecreds/#NewCredentials) 和 [NewCredentialsWithClient](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/ec2rolecreds/#NewCredentialsWithClient) 的用量，才能使用 [New](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds#New)。

 `ec2rolecreds` 套件的 `ec2rolecreds.New`採用 [ec2rolecreds.Options](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds#Options) 的功能選項做為輸入，可讓您覆寫要使用的特定 Amazon EC2 執行個體中繼資料服務用戶端，或覆寫憑證過期時段。

#### 範例
<a name="w2aac43c11c17b7"></a>

```
// 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
}
```

### 端點登入資料
<a name="endpoint-credentials"></a>

 您必須遷移 [NewCredentialsClient](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/endpointcreds/#NewCredentialsClient) 和 [NewProviderClient](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/endpointcreds/#NewProviderClient) 的用量，才能使用 [New](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds#New)。

 `endpointcreds` 套件的 `New`函數採用字串引數，其中包含 HTTP 或 HTTPS 端點的 URL 來擷取登入資料，以及 [endpointcreds.Options](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/endpointcreds#Options) 的功能選項來變更登入資料提供者並覆寫特定組態設定。

### 程序登入資料
<a name="process-credentials"></a>

 您必須遷移 [NewCredentials](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/processcreds/#NewCredentials)、[NewCredentialsCommand](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/processcreds/#NewCredentialsCommand) 和 [NewCredentialsTimeout](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/processcreds/#NewCredentialsTimeout) 的使用，才能使用 [NewProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/processcreds#New) 或 [NewProviderCommand](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/processcreds#NewProviderCommand)。

 `processcreds` 套件的 `NewProvider`函數採用字串引數，這是要在主機環境 shell 中執行的命令，以及 [選項](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/processcreds#Options)的功能選項，以變更登入資料提供者並覆寫特定組態設定。

 `NewProviderCommand` 接受 [NewCommandBuilder](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/processcreds#NewCommandBuilder) 界面的實作，該界面定義了更複雜的程序命令，這些命令可能需要一或多個命令列引數，或具有特定的執行環境需求。[DefaultNewCommandBuilder](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/processcreds#DefaultNewCommandBuilder) 會實作此界面，並為需要多個命令列引數的程序定義命令建置器。

#### 範例
<a name="example-2"></a>

```
// 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 登入資料
<a name="stslong-credentials"></a>

#### AssumeRole
<a name="assumerole"></a>

 您必須遷移 [NewCredentials](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/stscreds/#NewCredentials) 和 [NewCredentialsWithClient](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/stscreds/#NewCredentialsWithClient) 的用量，才能使用 [NewAssumeRoleProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds#NewAssumeRoleProvider)。

 `stscreds` 套件的 `NewAssumeRoleProvider`函數必須使用 [sts.Client](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts#Client) 呼叫，並從提供的 `sts.Client`設定登入資料中擔任 AWS Identity and Access Management 角色 ARN。您也可以提供一組 [AssumeRoleOptions](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds#AssumeRoleOptions) 的功能選項，以修改提供者的其他選用設定。

##### 範例
<a name="example-3"></a>

```
// 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
<a name="assumerolewithwebidentity"></a>

 您必須遷移 [NewWebIdentityCredentials](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/stscreds/#NewWebIdentityCredentials)、[NewWebIdentityRoleProvider](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/stscreds/#NewWebIdentityRoleProvider) 和 [NewWebIdentityRoleProviderWithToken](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/stscreds/#NewWebIdentityRoleProviderWithToken) 的用量，才能使用 [NewWebIdentityRoleProvider](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds#NewWebIdentityRoleProvider)。

 `stscreds` 套件的`NewWebIdentityRoleProvider`函數必須使用 [sts.Client](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts#Client) 呼叫，並使用提供的 `sts.Client`已設定的登入資料擔任 AWS Identity and Access Management 角色 ARN，以及用於提供 OAuth 2.0 或 OpenID Connect ID 字符的 [IdentityTokenRetriever](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds#IdentityTokenRetriever) 實作。[IdentityTokenFile](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds#IdentityTokenFile) 是 `IdentityTokenRetriever`，可用來從應用程式主機檔案系統上的檔案提供 Web 身分字符。您也可以提供一組 [WebIdentityRoleOptions](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/stscreds#WebIdentityRoleOptions) 的功能選項，以修改提供者的其他選用設定。

##### 範例
<a name="example-4"></a>

```
// 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
}
```

## 服務用戶端
<a name="service-clients"></a>

 適用於 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 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
```

### 用戶端建構
<a name="client-construction"></a>

 您可以使用用戶端套件中的 適用於 Go 的 AWS SDK `New`或 `NewFromConfig` 建構函數，在 中建構用戶端。從 適用於 Go 的 AWS SDK v1 遷移時，我們建議您使用 `NewFromConfig` 變體，這會使用來自 的值傳回新的服務用戶端`aws.Config`。值`aws.Config`將在使用 載入 SDK 共用組態時建立`config.LoadDefaultConfig`。如需建立服務用戶端的詳細資訊，請參閱 [搭配 AWS 服務使用 適用於 Go 的 AWS SDK v2](use-services.md)。

#### 範例 1
<a name="w2aac43c13c11b5"></a>

```
// 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：覆寫用戶端設定
<a name="example-2-overriding-client-settings"></a>

```
// 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"
})
```

### 端點
<a name="endpoints"></a>

 [端點](https://docs.aws.amazon.com/sdk-for-go/api/aws/endpoints/)套件不再存在於 中 適用於 Go 的 AWS SDK。每個服務用戶端現在都會將其所需的 AWS 端點中繼資料內嵌在用戶端套件中。這可減少編譯應用程式的整體二進位大小，不再包含應用程式未使用之服務的端點中繼資料。

 此外，每個服務現在都會公開自己的界面，以在 中解析端點`EndpointResolverV2`。每個 API 都會為服務 取得一組唯一的參數`EndpointParameters`，當叫用 操作時，這些參數的值是由 SDK 從各種位置取得。

 根據預設，服務用戶端會使用其設定 AWS 的區域來解析目標區域的服務端點。如果您的應用程式需要自訂端點，您可以在 `aws.Config`結構的 `EndpointResolverV2` 欄位上指定自訂行為。如果您的應用程式實作自訂[端點。解析程式](https://docs.aws.amazon.com/sdk-for-go/api/aws/endpoints/#Resolver)必須將其遷移以符合這個新的每個服務界面。

 如需端點和實作自訂解析程式的詳細資訊，請參閱 [設定用戶端端點](configure-endpoints.md)。

### 身分驗證
<a name="authentication"></a>

 適用於 Go 的 AWS SDK 支援更進階的身分驗證行為，這可讓您使用較新的 AWS 服務功能，例如 codecatalyst 和 S3 Express One Zone。此外，此行為可以根據每個用戶端進行自訂。

### 叫用 API 操作
<a name="invoking-api-operations"></a>

 服務用戶端操作方法的數量已大幅減少。`<OperationName>Request`、 `<OperationName>WithContext`和 `<OperationName>`方法都已合併為單一操作方法 `<OperationName>`。

#### 範例
<a name="example-5"></a>

 下列範例顯示如何將對 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
})
```

### 服務資料類型
<a name="service-data-types"></a>

 操作的最上層輸入和輸出類型可在服務用戶端套件中找到。指定操作的輸入和輸出類型遵循 `<OperationName>Input`和 的模式`<OperationName>Output`，其中 `OperationName`是您調用的操作名稱。例如，Amazon S3 PutObject 操作的輸入和輸出形狀分別為 [PutObjectInput](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#PutObjectInput) 和 [PutObjectOutput](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#PutObjectOutput)。

 除了輸入和輸出類型之外，所有其他服務資料類型都已遷移至位於服務用戶端`types`套件匯入路徑階層下的套件。例如，[s3.AccessControlPolicy](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/#AccessControlPolicy) 類型現在位於 [type.AccessControlPolicy](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3/types#AccessControlPolicy)。

#### 列舉值
<a name="enumeration-values"></a>

 開發套件現在為所有 API 列舉欄位提供類型體驗。您現在可以使用服務用戶端`types`套件中找到的其中一種具體類型，而不是使用從服務 API 參考文件中複製的字串常值。例如，您可以為 Amazon S3 PutObjectInput 操作提供要套用至物件的 ACL。在 適用於 Go 的 AWS SDK v1 中，此參數是一種`*string`類型。在 中 適用於 Go 的 AWS SDK，此參數現在是 [type.ObjectCannedACL](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3/types#ObjectCannedACL)。`types` 套件為可指派給此欄位的有效列舉值提供產生的常數。例如[，type.ObjectCannedACLPrivate](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3/types#ObjectCannedACLPrivate) 是「私有」固定 ACL 值的常數。此值可用來代替管理應用程式中的字串常數。

### 指標參數
<a name="pointer-parameters"></a>

 針對所有輸入參數傳遞至服務操作所需的 適用於 Go 的 AWS SDK v1 指標參考。 適用於 Go 的 AWS SDK v2 已簡化大多數 服務的體驗，盡可能不需要將輸入值做為指標傳遞。此變更表示許多服務用戶端操作不再需要您的應用程式傳遞下列類型的指標參考：`uint8`、`uint16`、`uint32`、`int8`、`int16``int32`、`float32`、`float64`、、`bool`。同樣地，配量和映射元素類型也隨之更新，以反映其元素是否必須做為指標參考傳遞。

 [aws](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws) 套件包含協助程式函數，用於建立 Go 內建類型的指標，這些協助程式應該用來更輕鬆地處理這些 Go 類型的建立指標類型。同樣地，也為這些類型的安全取消參考指標值提供了協助程式方法。例如，[aws.String](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#String) 函數會從 `string` ⇒ 轉換`*string`。反之，[aws.ToString](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#ToString) 會從 `*string` ⇒ 轉換`string`。從 適用於 Go 的 AWS SDK v1 升級至 v2 時，您必須遷移協助程式的使用量，以便從指標類型轉換為非指標變體。例如，[aws.StringValue](https://docs.aws.amazon.com/sdk-for-go/api/aws/#StringValue) 必須更新為 `aws.ToString`。

### 錯誤類型
<a name="errors-types"></a>

 適用於 Go 的 AWS SDK 充分利用 [Go 1.13 中引入](https://go.dev/blog/go1.13-errors)的錯誤包裝功能。建立錯誤回應模型的服務在其用戶端的`types`套件中產生了可用的類型，可用於測試用戶端操作錯誤是否由這些類型之一造成。例如，如果嘗試擷取不存在的物件金鑰，Amazon S3 `GetObject`操作可能會傳回`NoSuchKey`錯誤。您可以使用 [errors.As](https://pkg.go.dev/errors#As) 來測試傳回的操作錯誤是否為[類型。NoSuchKey](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3/types#NoSuchKey) 錯誤。如果服務未針對錯誤建立特定類型的模型，您可以使用 [smithy.APIError](https://pkg.go.dev/github.com/aws/smithy-go#APIError) 介面類型來檢查傳回的錯誤碼和來自服務的訊息。此功能會取代 v1 中的 [awserr.Error](https://docs.aws.amazon.com/sdk-for-go/api/aws/awserr//#Error) 和其他 [awserr](https://docs.aws.amazon.com/sdk-for-go/api/aws/awserr/) 功能。 適用於 Go 的 AWS SDK 如需處理錯誤的詳細資訊，請參閱 [處理 適用於 Go 的 AWS SDK V2 中的錯誤](handle-errors.md)。

#### 範例
<a name="example-6"></a>

```
// 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
}
```

### 分頁程式
<a name="paginators"></a>

 服務操作分頁程式不再被叫用為服務用戶端上的方法。若要將分頁器用於 操作，您必須使用其中一種分頁器建構器方法來建構 操作的分頁器。例如，若要透過 Amazon S3 `ListObjectsV2`操作使用分頁，您必須使用 [s3.NewListObjectsV2Paginator 建構其分頁程式。](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#NewListObjectsV2Paginator)此建構函數會傳回 [ListObjectsV2Paginator](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#ListObjectsV2Paginator) 提供方法 `HasMorePages`，並`NextPage`用於判斷是否有更多頁面可擷取和叫用操作來分別擷取下一頁。如需使用 SDK 分頁程式的詳細資訊，請參閱 [使用操作分頁器](using.md#using-operation-paginators)。

 讓我們看看如何從 適用於 Go 的 AWS SDK v1 分頁器遷移到 適用於 Go 的 AWS SDK v2 對等項目的範例。

#### 範例
<a name="example-7"></a>

```
// 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)
```

### 等待程式
<a name="waiters"></a>

 服務操作等待程式不再被叫用為服務用戶端上的方法。若要使用等待程式，請先建構所需的等待程式類型，然後叫用等待方法。例如，若要等待 Amazon S3 儲存貯體存在，您必須建構`BucketExists`等待程式。使用 [s3.NewBucketExistsWaiter](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#NewBucketExistsWaiter) 建構函數來建立 [s3.BucketExistsWaiter](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#BucketExistsWaiter)。`s3.BucketExistsWaiter` 提供一種`Wait`方法，可用來等待儲存貯體變成可用。

### 預先簽章的請求
<a name="presigned-requests"></a>

 V1 SDK 在技術上支援預先簽署*任何* AWS SDK 操作，不過，這無法準確地代表服務層級實際支援的內容 （實際上，大多數 AWS 服務操作不支援預先簽署）。

 適用於 Go 的 AWS SDK 會針對支援的可預先簽章操作，使用特定 API 公開服務套件中的特定`PresignClient`實作，以解決此問題。 APIs 

 **注意：如果服務缺少您在 SDK v1 中成功使用的 操作的預先簽署支援，請在 [ GitHub 上提出問題](https://github.com/aws/aws-sdk-go-v2/issues)，讓我們知道。**

 [Presign ](https://docs.aws.amazon.com/sdk-for-go/api/aws/request/#Request.Presign)和 [PresignRequest](https://docs.aws.amazon.com/sdk-for-go/api/aws/request/#Request.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)
}
```

## 請求自訂
<a name="request-customization"></a>

 單體 [request.Request](https://docs.aws.amazon.com/sdk-for-go/api/aws/request/#Request) API 已重新箱體化。

### 操作輸入/輸出
<a name="operation-inputoutput"></a>

 分別`Data`保留操作輸入和輸出結構的不透明`Request`欄位 `Params`和 ，現在可於特定中介軟體階段內做為輸入/輸出存取：

 請求參考 `Request.Params`和 `Request.Data` 必須遷移至中介軟體的處理常式。

#### 遷移 `Params`
<a name="migrating-params"></a>

```
// 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`
<a name="migrating-data"></a>

```
// 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 請求/回應
<a name="http-requestresponse"></a>

 來自 的 `HTTPRequest`和 `HTTPResponse` 欄位現在`Request`會在特定中介軟體階段公開。由於中介軟體與傳輸無關，您必須對中介軟體輸入或輸出執行類型聲明，以顯示基礎 HTTP 請求或回應。

 請求參考 `Request.HTTPRequest`和 `Request.HTTPResponse` 必須遷移至中介軟體的處理常式。

#### 遷移 `HTTPRequest`
<a name="migrating-httprequest"></a>

```
// 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", "..."))
    // ...
}
```

### 處理常式階段
<a name="handler-phases"></a>

 SDK v2 中介軟體階段是 v1 處理常式階段的後續版本。

 下表提供 v1 處理常式階段的粗略映射至其在 V2 中介軟體堆疊內的同等位置：


|  v1 處理常式名稱  |  v2 中介軟體階段  | 
| --- | --- | 
|  驗證  |  初始化  | 
|  建置  |  序列化  | 
|  符號  |  完成  | 
|  傳送  |  不適用 (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
}
```

## 功能
<a name="features"></a>

### Amazon EC2 執行個體中繼資料服務
<a name="ec2-instance-metadata-service"></a>

 適用於 Go 的 AWS SDK 提供 Amazon EC2 執行個體中繼資料服務 (IMDS) 用戶端，您可以在 Amazon EC2 執行個體上執行應用程式時用來查詢本機 IMDS。IMDS 用戶端是獨立的 Go 模組，可使用 新增至您的應用程式 

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

 用戶端建構函數和方法操作已更新，以符合其他 SDK 服務用戶端的設計。

#### 範例
<a name="example-8"></a>

```
// 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
<a name="s3-transfer-manager"></a>

 Amazon S3 Transfer Manager 可用於同時管理物件的上傳和下載。此套件位於服務用戶端匯入路徑之外的 Go 模組中。您可以使用 擷取此模組`go get github.com/aws/aws-sdk-go-v2/feature/s3/manager`。

 [s3.NewUploader](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3manager/#NewUploader) 和 [s3.NewUploaderWithClient](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3manager/#NewUploaderWithClient) 已取代為建構函數方法 [manager.NewUploader](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#)，用於建立 Upload Manager 用戶端。

 [s3.NewDownloader](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3manager/#NewDownloader) 和 [s3.NewDownloaderWithClient](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3manager/#NewDownloaderWithClient) 已取代為單一建構函式方法[管理員。NewDownloader](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#NewDownloader) 用於建立 Download Manager 用戶端。

### Amazon CloudFront 簽署公用程式
<a name="cflong-signing-utilities"></a>

 在服務用戶端匯入路徑之外的 Go 適用於 Go 的 AWS SDK 模組中提供 Amazon CloudFront 簽署公用程式。可以使用 擷取此模組`go get`。

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

### Amazon S3 加密用戶端
<a name="s3-encryption-client"></a>

 從 開始 適用於 Go 的 AWS SDK，Amazon S3 加密用戶端是[AWS 加密工具](https://docs.aws.amazon.com/aws-crypto-tools)下的個別模組。Go 的最新版本 S3 加密用戶端 3.x 現已在 [GitHub](https://github.com/aws/amazon-s3-encryption-client-go) 提供。可以使用 擷取此模組`go get`：

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

 個別 `EncryptionClient`([v1](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3crypto/#EncryptionClient)、[v2](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3crypto/#EncryptionClientV2)) 和 `DecryptionClient`([v1](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3crypto/#DecryptionClient)、[v2](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3crypto/#DecryptionClientV2)) APIs 已取代為單一用戶端 [S3EncryptionClientV3](https://pkg.go.dev/github.com/aws/amazon-s3-encryption-client-go/v3/client#S3EncryptionClientV3)，公開加密和解密功能。

 如同 中的其他 服務用戶端 適用於 Go 的 AWS SDK，操作 APIs 已壓縮：
+  `GetObject`、 `GetObjectRequest`和 `GetObjectWithContext` 解密 APIs 會由 [GetObject](https://pkg.go.dev/github.com/aws/amazon-s3-encryption-client-go/v3/client#S3EncryptionClientV3.GetObject) 取代。
+  [PutObject](https://pkg.go.dev/github.com/aws/amazon-s3-encryption-client-go/v3/client#S3EncryptionClientV3.PutObject) 會取代 `PutObjectRequest`、 `PutObject`和 `PutObjectWithContext`加密 API。 APIs 

 若要了解如何遷移至 3.x 主要版本的加密用戶端，請參閱[本指南](https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/go-v3-migration.html)。

## 服務自訂變更
<a name="service-customizations-changes"></a>

### Amazon S3
<a name="s3"></a>

 從 適用於 Go 的 AWS SDK v1 遷移到 v2 時，需要注意的重要變更包括使用客戶提供的金鑰 (SSE-C) 處理`SSECustomerKey`用於伺服器端加密的 。在 適用於 Go 的 AWS SDK v1 中， `SSECustomerKey` 對 Base64 的編碼是由 SDK 在內部處理。在 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
```