

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

# の使用AWS SDK for Go
<a name="using"></a>

アプリケーションで AWS SDK for Go を使用してプログラミングを行う際の、一般的かつ推奨される方法について説明します。

**Topics**
+ [サービスクライアントの作成](#constructing-a-service-client)
+ [サービスオペレーションの呼び出し](#calling-service-operations)
+ [サービスクライアントの同時使用](#concurrently-using-service-clients)
+ [オペレーションページネーターの使用](#using-operation-paginators)
+ [ウェーターを使用する](#using-waiters)
+ [SDK でのエラー処理](handle-errors.md)

## サービスクライアントの作成
<a name="constructing-a-service-client"></a>

 サービスクライアントは、サービスクライアントの Go パッケージに含まれている `New` または `NewFromConfig` 関数を使用して作成できます。これらの関数はいずれも、サービス API を呼び出すメソッドを含む `Client` 構造体型を返します。`New` と `NewFromConfig` はどちらもクライアントの作成用に同じ設定オプションを提供しますが、作成パターンに若干の違いがあります。詳細については、以降のセクションで説明します。

### NewFromConfig
<a name="newfromconfig"></a>

 `NewFromConfig` 関数は、[aws.Config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Config) を使用してサービスクライアントを作成するための一貫したインターフェイスを提供します。`aws.Config` は、[config.LoadDefaultConfig](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#LoadDefaultConfig) を使用してロードできます。`aws.Config` の作成の詳細については、「[SDK を設定](configure-gosdk.md)」を参照してください。次の例では、`aws.Config` および `NewFromConfig` 関数を使用して Amazon S3 サービスクライアントを作成する方法を示しています。

```
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 {
        panic(err)
    }
    
    client := s3.NewFromConfig(cfg)
```

#### 設定のオーバーライド
<a name="overriding-configuration"></a>

 `NewFromConfig` には、クライアントの設定 `Options` 構造体を変更できる関数型引数を 1 つ以上渡すことができます。これにより、リージョンの変更や、Amazon S3 の `UseAccelerate` オプションといったサービス固有のオプションの変更など、特定のオーバーライドが可能になります。例: 

```
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 {
        panic(err)
    }
    
    client := s3.NewFromConfig(cfg, func(o *s3.Options) {
        o.Region = "us-west-2"
        o.UseAccelerate = true
    })
```

 クライアントの `Options` 値に対するオーバーライドは、`NewFromConfig` に渡される関数型引数の順序によって決まります。

### 新
<a name="new"></a>

**注記**  
 `New` は、クライアントのより高度な作成方法と見なされています。`NewFromConfig` を使用してクライアントを作成することをお勧めします。`aws.Config` 構造体を使用した作成が可能になるためです。これにより、アプリケーションで必要な各サービスクライアントのために `Options` 構造体インスタンスを個別に作成する必要がなくなります。

 `New` 関数はクライアントコンストラクタです。クライアントパッケージの `Options` 構造体のみを使用してクライアントを作成するためのインターフェイスを提供します。例えば、`New` を使用して Amazon S3 クライアントを作成するには、次のようにします。

```
import "github.com/aws/aws-sdk-go-v2/aws"
    import "github.com/aws/aws-sdk-go-v2/credentials"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ...
    
    client := s3.New(s3.Options{
        Region:      "us-west-2",
        Credentials: aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")),
    })
```

#### 設定のオーバーライド
<a name="overriding-configuration-1"></a>

 `New` には、クライアントの設定 `Options` 構造体を変更できる関数型引数を 1 つ以上渡すことができます。これにより、リージョンの変更や、Amazon S3 の `UseAccelerate` オプションといったサービス固有のオプションの変更など、特定のオーバーライドが可能になります。例: 

```
import "github.com/aws/aws-sdk-go-v2/aws"
    import "github.com/aws/aws-sdk-go-v2/credentials"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ...
    
    options := s3.Options{
        Region:      "us-west-2",
        Credentials: aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")),
    }
    
    client := s3.New(options, func(o *s3.Options) {
        o.Region = "us-east-1"
        o.UseAccelerate = true
    })
```

 クライアントの `Options` 値に対するオーバーライドは、`New` に渡される関数型引数の順序によって決まります。

## サービスオペレーションの呼び出し
<a name="calling-service-operations"></a>

 サービスクライアントのインスタンスを作成した後、それを使用してサービスのオペレーションを呼び出すことができます。例えば、Amazon S3 の `GetObject` オペレーションを呼び出すには、次のようにします。

```
response, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
        Bucket: aws.String("amzn-s3-demo-bucket"),
        Key:    aws.String("obj-key"),
    })
```

 サービスオペレーションを呼び出すと、SDK は入力を同期的に検証し、リクエストをシリアル化し、認証情報で署名して AWS に送信します。その後、レスポンスまたはエラーを逆シリアル化します。ほとんどの場合、サービスオペレーションを直接呼び出すことができます。各サービスオペレーションのクライアントメソッドは、オペレーションのレスポンス構造体とエラーのインターフェイス型を返します。サービスオペレーションのレスポンス構造体にアクセスする前に、`error` 型を必ず確認してエラーの有無を判断する必要があります。

### サービスオペレーションへのパラメータの受け渡し
<a name="passing-parameters-to-a-service-operation"></a>

 サービスの各オペレーションは、それぞれのメソッドで [context.Context](https://golang.org/pkg/context/#Context) 値を受け取り、リクエストの期限などを設定できます。これらの期限は SDK によって適用されます。また、各サービスオペレーションは、それぞれのサービスの Go パッケージに含まれている `<OperationName>Input` 構造体を受け取ります。API の入力パラメータは、オペレーションの入力構造体を使用して渡します。

 オペレーションの入力構造体には、標準の Go 型 (数値型、boolean 型、文字列型、マップ型、リスト型など) のパラメータを含めることができます。より複雑な API オペレーションでは、入力パラメータのより複雑なモデル化を行う場合があります。サービス固有の構造体や列挙型などは、そのサービスの `types` Go パッケージに含まれています。

 また、サービスによっては、Go 型のデフォルト値とユーザーが明示的に設定した値かを区別する場合があります。そのような場合、対象の型へのポインタ参照で値を渡す必要があります。数値、boolean、文字列などの標準的な Go 型では、変換を容易にするために、[aws](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws) パッケージには `<Type>` と `From<Type>` という便利な関数が用意されています。例えば、[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` 型に変換できます。同時に、nil ポインタの参照先取得 (dereference) を防ぐこともできます。これらの `To<Type>` 関数は、サービスのレスポンスを処理する際に便利です。

 次に示しているのは、Amazon S3 クライアントを使用して `GetObject` API を呼び出し、`types` パッケージと `aws.<Type>` ヘルパーを使用して入力を作成する方法の例です。

```
import "context"
    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())
    if err != nil {
        panic(err)
    }
    
    client := s3.NewFromConfig(cfg)
    
    resp, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
        Bucket:       aws.String("amzn-s3-demo-bucket"),
        Key:          aws.String("keyName"),
        RequestPayer: types.RequestPayerRequester,
    })
```

### オペレーション呼び出し時のクライアントオプションのオーバーライド
<a name="overriding-client-options"></a>

 関数型引数を使用してクライアントを作成する際にクライアントのオペレーションのオプションを変更できるのと同様に、サービスのオペレーションメソッドの呼び出し時にも 1 つ以上の関数型引数を渡してクライアントのオプションを変更できます。このアクションはスレッドセーフであり、クライアント上の他の並行オペレーションには影響しません。

 例えば、クライアントのリージョンを「us-west-2」から「us-east-1」に変更するには、次のようにします。

```
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-west-2"))
    if err != nil {
        log.Printf("error: %v", err)
        return
    }
    
    client := s3.NewFromConfig(cfg)
    
    params := &s3.GetObjectInput{
        // ...
    }
    
    resp, err := client.GetObject(context.TODO(), params, func(o *Options) {
        o.Region = "us-east-1"
    })
```

### オペレーションレスポンスの処理
<a name="handling-operation-responses"></a>

 サービスの各オペレーションメソッドには、レスポンスメンバーを含む出力構造体が関連付けられています。出力構造体の名前は `<OperationName>Output` というパターンに従っています。オペレーションによっては、出力構造体にメンバーが定義されていない場合もあります。サービスのオペレーションを呼び出した後は、`error` 引数の型を必ず確認して、そのオペレーション実行中のエラーの有無を判断する必要があります。返されるエラーは、クライアント側の入力検証エラーから、クライアントに返されるサービス側のエラーレスポンスまで多岐にわたります。クライアントから nil 以外のエラーが返された場合は、オペレーションの出力構造体にアクセスしないようにしてください。

 例えば、オペレーションエラーをログに記録し、呼び出し元の関数から早期に制御を戻すには、次のようにします。

```
response, err := client.GetObject(context.TODO())
    if err != nil {
        log.Printf("GetObject error: %v", err)
        return
    }
```

 特定のエラータイプの確認方法を含むエラー処理の詳細については、TODO (参照先は今後提供予定) を参照してください。

#### `io.ReadCloser` を含むレスポンス
<a name="responses-with-ioreadcloser"></a>

 API オペレーションによっては、出力メンバーとして `io.ReadCloser` を含むレスポンス構造体を返す場合もあります。これに該当するのは、HTTP レスポンス本文に一部の出力要素を含める API オペレーションの場合です。

 例えば、Amazon S3 の `GetObject` オペレーションでは、オブジェクトのペイロードにアクセスするための `io.ReadCloser` である `Body` メンバーを含むレスポンスを返します。

**警告**  
 出力メンバーの内容を使用したかどうかにかかわらず、`io.ReadCloser` のすべての出力メンバーに対しては `Close()` を必ず実行するようにしてください。この処理を実行しないと、リソースリークが発生し、以降呼び出されるオペレーションでレスポンス本文の読み取りに問題が発生する可能性があります。

```
resp, err := s3svc.GetObject(context.TODO(), &s3.GetObjectInput{...})
    if err != nil {
        // handle error
        return
    }
    // Make sure to always close the response Body when finished
    defer resp.Body.Close()
    
    decoder := json.NewDecoder(resp.Body)
    if err := decoder.Decode(&myStruct); err != nil {
        // handle error
        return
    }
```

#### レスポンスメタデータ
<a name="response-metadata"></a>

 サービスのすべてのオペレーションの出力構造体には、型 [middleware.Metadata](https://pkg.go.dev/github.com/aws/smithy-go/middleware#Metadata) の `middleware.Metadata` メンバーが含まれています。`ResultMetadata` は、サービスによってモデル化されていないレスポンス情報を SDK のミドルウェアが取得するために使用されます。これには `RequestID` などのメタデータが含まれます。例えば、AWS サポートによるリクエストのトラブルシューティングに役立つように、サービスのレスポンスに関連付けられた `RequestID` を取得するには、次のようにします。

```
import "fmt"
    import "log"
    import "github.com/aws/aws-sdk-go-v2/aws/middleware"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ..
    
    resp, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
        // ...
    })
    if err != nil {
        log.Printf("error: %v", err)
        return
    }
    
    requestID, ok := middleware.GetRequestIDMetadata(resp.ResultMetadata)
    if !ok {
        fmt.Println("RequestID not included with request")
    }
    
    fmt.Printf("RequestID: %s\n", requestID)
```

## サービスクライアントの同時使用
<a name="concurrently-using-service-clients"></a>

 同じサービスクライアントを複数の goroutine で同時に使用して、複数のリクエストを送信できます。サービスクライアントは任意の数の goroutine で使用できます。

 次の例では、Amazon S3 サービスクライアントを複数の goroutine で使用しています。この例では、2 つのオブジェクトを Amazon S3 バケットに同時にアップロードします。

```
import "context"
    import "log"
    import "strings"
    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 {
        log.Printf("error: %v", err)
        return
    }
    
    client := s3.NewFromConfig(cfg)
    
    type result struct {
        Output *s3.PutObjectOutput
        Err    error
    }
    
    results := make(chan result, 2)
    
    var wg sync.WaitGroup
    wg.Add(2)
    
    go func() {
    defer wg.Done()
        output, err := client.PutObject(context.TODO(), &s3.PutObjectInput{
            Bucket: aws.String("amzn-s3-demo-bucket"),
            Key:    aws.String("foo"),
            Body:   strings.NewReader("foo body content"),
        })
        results <- result{Output: output, Err: err}
    }()
    
    go func() {
        defer wg.Done()
        output, err := client.PutObject(context.TODO(), &s3.PutObjectInput{
            Bucket: aws.String("amzn-s3-demo-bucket"),
            Key:    aws.String("bar"),
            Body:   strings.NewReader("bar body content"),
        })
        results <- result{Output: output, Err: err}
    }()
    
    wg.Wait()
    
    close(results)
    
    for result := range results {
        if result.Err != nil {
            log.Printf("error: %v", result.Err)
            continue
        }
        fmt.Printf("etag: %v", aws.ToString(result.Output.ETag))
    }
```

## オペレーションページネーターの使用
<a name="using-operation-paginators"></a>

 通常、アイテムのリストを取得するときは、出力構造体でトークンやマーカーを確認して、AWS サービスがすべての結果を返したかどうかを判断する必要があります。トークンやマーカーが存在する場合は、それを使用して次のページの結果をリクエストします。これらのトークンやマーカーを自分で管理する代わりに、サービスパッケージで提供されているページネーター型を使用できます。

 ページネーターヘルパーは、サポートされているサービスオペレーションで使用でき、サービスクライアントの Go パッケージに含まれています。サポートされているオペレーションのページネーターを作成するには、`New<OperationName>Paginator` 関数を使用します。ページネーターコンストラクタは、サービスの `Client`、オペレーションの `<OperationName>Input` 入力パラメータ、および他のオプションのページネーター設定を構成するための関数型引数 (任意) を引数として受け取ります。

 返されるオペレーションページネーター型を使用すれば、ページ分割されたオペレーションを簡単に反復処理できます。最終ページに到達するか、アプリケーションが探している項目を見つけるまで処理を続行できます。ページネーター型には `HasMorePages` と `NextPage` の 2 つのメソッドがあります。`HasMorePages` は、最初のページがまだ取得されていない場合や、追加のページが存在する場合に boolean 値の `true` を返します。オペレーションの最初または後続のページを取得するには、`NextPage` オペレーションを呼び出す必要があります。`NextPage` は `context.Context` を受け取り、オペレーションの出力および対応するエラーを返します。クライアントのオペレーションメソッドの戻り値と同様に、返されるレスポンス構造体を使用する前に、返されるエラーを必ず確認する必要があります。「[オペレーションレスポンスの処理](#handling-operation-responses)」を参照してください。

 次の例では、`ListObjectsV2` ページネーターを使用して、`ListObjectV2` オペレーションから最大 3 ページ分のオブジェクトキーのリストを取得しています。各ページには最大 10 個のキーが含まれており、これは `Limit` ページネーターオプションで定義されています。

```
import "context"
    import "log"
    import "github.com/aws/aws-sdk-go-v2/config"
    import "github.com/aws/aws-sdk-go-v2/aws"
    import "github.com/aws/aws-sdk-go-v2/service/s3"
    
    // ...
    
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Printf("error: %v", err)
        return
    }
    
    client := s3.NewFromConfig(cfg)
    
    params := &s3.ListObjectsV2Input{
        Bucket: aws.String("amzn-s3-demo-bucket"),
    }
    
    paginator := s3.NewListObjectsV2Paginator(client, params, func(o *s3.ListObjectsV2PaginatorOptions) {
        o.Limit = 10
    })
    
    pageNum := 0
    for paginator.HasMorePages() && pageNum < 3 {
        output, err := paginator.NextPage(context.TODO())
        if err != nil {
            log.Printf("error: %v", err)
            return
        }
        for _, value := range output.Contents {
            fmt.Println(*value.Key)
        }
        pageNum++
    }
```

 クライアントオペレーションメソッドと同様に、`NextPage` に関数型引数を 1 つ以上渡すことで、リクエストリージョンなどのクライアントオプションを変更できます。オペレーションを呼び出すときのクライアントオプションのオーバーライドの詳細については、「[オペレーション呼び出し時のクライアントオプションのオーバーライド](#overriding-client-options)」を参照してください。

## ウェーターを使用する
<a name="using-waiters"></a>

 非同期の AWS API とやり取りする場合、特定のリソースに対してさらなるアクションを実行するために、そのリソースが使用可能になるまで待機する必要があることがよくあります。

 例えば、Amazon DynamoDB の `CreateTable` API は TableStatus として CREATING をすぐに返しますが、ステータスが `ACTIVE` に変わるまでは、読み書きオペレーションを呼び出すことはできません。

 テーブルのステータスを定期的にポーリングするロジックを自分で記述するのは、手間がかかりエラーの原因にもなります。ウェーターは、この複雑な処理を簡略化し、ポーリングを自動的に実行するシンプルな API です。

 例えば、DynamoDB テーブルが作成されて書き込みオペレーションが可能かどうかをポーリングするために、ウェーターを使用できます。

```
import "context"
    import "fmt"
    import "log"
    import "time"
    import "github.com/aws/aws-sdk-go-v2/aws"
    import "github.com/aws/aws-sdk-go-v2/config"
    import "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    
    // ...
    
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Printf("error: %v", err)
        return
    }
    
    client := dynamodb.NewFromConfig(cfg)
    
    // we create a waiter instance by directly passing in a client
    // that satisfies the waiters client Interface. 
    waiter :=  dynamodb.NewTableExistsWaiter(client)
    
    // params is the input to api operation used by the waiter
    params := &dynamodb.DescribeTableInput {
        TableName: aws.String("test-table")
    }
    
    // maxWaitTime is the maximum wait time, the waiter will wait for 
    // the resource status.
    maxWaitTime := 5 * time.Minutes
    
    // Wait will poll until it gets the resource status, or max wait time 
    // expires.
    err := waiter.Wait(context.TODO(), params, maxWaitTime)  
    if err != nil {
        log.Printf("error: %v", err)
        return 
    }
    fmt.Println("Dynamodb table is now ready for write operations")
```

### ウェーター設定のオーバーライド
<a name="overriding-waiter-configuration"></a>

 デフォルトでは、SDK は AWS サービスが各 API に対して最適と定義した最小および最大の遅延値を使用します。ウェーターの作成時やオペレーションの呼び出し時に関数型オプションを指定することで、ウェーター設定をオーバーライドできます。

 例えば、ウェーターの作成時に設定をオーバーライドするには、次のようにします。

```
import "context"
    import "fmt"
    import "log"
    import "time"
    import "github.com/aws/aws-sdk-go-v2/aws"
    import "github.com/aws/aws-sdk-go-v2/config"
    import "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    
    // ...
    
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Printf("error: %v", err)
        return
    }
    
    client := dynamodb.NewFromConfig(cfg)
    
    // we create a waiter instance by directly passing in a client
    // that satisfies the waiters client Interface. 
    waiter :=  dynamodb.NewTableExistsWaiter(client, func (o *dynamodb.TableExistsWaiterOptions) {
        
        // override minimum delay to 10 seconds
        o.MinDelay = 10 * time.Second
        
        // override maximum default delay to 300 seconds
        o.MaxDelay = 300 * time.Second
    })
```

各ウェーターの `Wait` 関数でも関数型オプションを受け取ることができます。上記の例と同様に、`Wait` リクエストごとにウェーター設定をオーバーライドできます。

```
// params is the input to api operation used by the waiter
    params := &dynamodb.DescribeTableInput {
        TableName: aws.String("test-table")
    }
    
    // maxWaitTime is the maximum wait time, the waiter will wait for 
    // the resource status.
    maxWaitTime := 5 * time.Minutes
    
    // Wait will poll until it gets the resource status, or max wait time 
    // expires.
    err := waiter.Wait(context.TODO(), params, maxWaitTime, func (o *dynamodb.TableExistsWaiterOptions) {
    
        // override minimum delay to 5 seconds
        o.MinDelay = 5 * time.Second
    
        // override maximum default delay to 120 seconds
        o.MaxDelay = 120 * time.Second
    })
    if err != nil {
        log.Printf("error: %v", err)
        return 
    }
    fmt.Println("Dynamodb table is now ready for write operations")
```

### 高度なウェーター設定のオーバーライド
<a name="advanced-waiter-configuration-overrides"></a>

 再試行可能なカスタム関数を指定することで、ウェーターのデフォルト動作をカスタマイズすることもできます。ウェーター固有のオプションでは、[オペレーションのミドルウェアをカスタマイズ](middleware.md#writing-a-custom-middleware)するための `APIOptions` も提供されています。

 例えば、高度なウェーター設定のオーバーライドを定義するには、次のようにします。

```
import "context"
    import "fmt"
    import "log"
    import "time"
    import "github.com/aws/aws-sdk-go-v2/aws"
    import "github.com/aws/aws-sdk-go-v2/config"
    import "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    import "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
    // ...
    
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Printf("error: %v", err)
        return
    }
    
    client := dynamodb.NewFromConfig(cfg)
    
    // custom retryable defines if a waiter state is retryable or a terminal state.
    // For example purposes, we will configure the waiter to not wait 
    // if table status is returned as `UPDATING`
    customRetryable := func(ctx context.Context, params *dynamodb.DescribeTableInput, 
        output *dynamodb.DescribeTableOutput, err error) (bool, error) {
        if output.Table != nil {
            if output.Table.TableStatus == types.TableStatusUpdating {
                // if table status is `UPDATING`, no need to wait
                return false, nil   
            }
        }
    }
    
    // we create a waiter instance by directly passing in a client
    // that satisfies the waiters client Interface. 
    waiter :=  dynamodb.NewTableExistsWaiter(client, func (o *dynamodb.TableExistsWaiterOptions) {
        
        // override the service defined waiter-behavior
        o.Retryable = customRetryable
    })
```