

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Uso de AWS SDK para Go
<a name="using"></a>

Aprenda formas comunes y recomendadas de programar con AWS SDK para Go en las aplicaciones.

**Topics**
+ [Creación de un cliente de servicio](#constructing-a-service-client)
+ [Llamada a operaciones de servicio](#calling-service-operations)
+ [Uso simultáneo de clientes de servicio](#concurrently-using-service-clients)
+ [Uso de paginadores de operaciones](#using-operation-paginators)
+ [Uso de esperadores](#using-waiters)
+ [Gestión de errores en el SDK](handle-errors.md)

## Creación de un cliente de servicio
<a name="constructing-a-service-client"></a>

 Los clientes de servicio se pueden crear mediante las funciones `New` o `NewFromConfig` disponibles en el paquete Go del cliente de servicio. Cada función devolverá un tipo de estructura `Client` que contiene los métodos para invocar las API de servicio. `New` y `NewFromConfig` proporcionan el mismo conjunto de opciones configurables para crear un cliente de servicio, pero ofrecen patrones de creación distintos que veremos en las secciones posteriores. 

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

 La función `NewFromConfig` proporciona una interfaz coherente para crear clientes de servicio mediante [aws.Config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Config). `aws.Config` se puede cargar mediante [config.LoadDefaultConfig](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#LoadDefaultConfig). Para obtener más información sobre cómo crear una instancia de `aws.Config`, consulte [Configurar el SDK](configure-gosdk.md). En el siguiente ejemplo se muestra cómo crear un cliente de servicio Amazon S3 mediante `aws.Config` y la función `NewFromConfig`: 

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

#### Reemplazo de la configuración
<a name="overriding-configuration"></a>

 `NewFromConfig` puede tomar uno o más argumentos funcionales que pueden modificar la estructura `Options` de configuración de un cliente. Esto le permite realizar reemplazos específicos, como cambiar la región o modificar opciones específicas del servicio (por ejemplo, la opción `UseAccelerate` de Amazon S3). Por ejemplo: 

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

 Los reemplazos del valor `Options` del cliente vienen determinados por el orden en el que se asignan los argumentos funcionales a `NewFromConfig`. 

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

**nota**  
 `New` se considera una forma más avanzada de creación de clientes. Le recomendamos que utilice `NewFromConfig` para la creación de clientes, ya que permite crear con la estructura de `aws.Config`. Esto elimina la necesidad de crear una instancia de estructura `Options` para cada cliente de servicio que requiera la aplicación. 

 `New` es una función creadora de clientes que proporciona una interfaz de creación de clientes con el uso exclusivo de la estructura `Options` de los paquetes de clientes para definir las opciones de configuración del cliente. Por ejemplo, para crear un cliente de Amazon S3 mediante `New`: 

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

#### Reemplazo de la configuración
<a name="overriding-configuration-1"></a>

 `New` puede tomar uno o más argumentos funcionales que pueden modificar la estructura `Options` de configuración de un cliente. Esto le permite realizar reemplazos específicos, como cambiar la región o modificar opciones específicas del servicio (por ejemplo, la opción `UseAccelerate` de Amazon S3). Por ejemplo: 

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

 Los reemplazos del valor `Options` del cliente vienen determinados por el orden en el que se asignan los argumentos funcionales a `New`. 

## Llamada a operaciones de servicio
<a name="calling-service-operations"></a>

 Una vez que tenga una instancia de cliente de servicio, puede usarla para llamar a las operaciones de un servicio. Por ejemplo, para llamar a la operación `GetObject` de Amazon S3: 

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

 Al llamar a una operación de servicio, el SDK valida de forma sincrónica la entrada, serializa la solicitud, la firma con sus credenciales, la envía a AWS y, a continuación, deserializa una respuesta o un error. En la mayoría de los casos, puede llamar a las operaciones de servicio de forma directa. Cada método de cliente para operaciones de servicio devolverá una estructura de respuesta de la operación y un tipo de interfaz de error. Compruebe siempre el tipo `error` para determinar si se ha producido un error antes de intentar acceder a la estructura de respuesta de la operación de servicio. 

### Transferencia de parámetros a una operación de servicio
<a name="passing-parameters-to-a-service-operation"></a>

 Cada método de operación de servicio toma un valor [context.Context](https://golang.org/pkg/context/#Context) que se puede utilizar para establecer plazos de solicitud que el SDK cumplirá. Además, cada operación de servicio tomará una estructura `<OperationName>Input` que se encuentra en el paquete Go respectivo del servicio. Para transferir los parámetros de entrada de la API use la estructura de entrada de la operación. 

 Las estructuras de entrada de la operación pueden tener parámetros de entrada como los tipos numérico, booleano, de cadena, de mapa y de lista Go estándar. En operaciones de la API más complejas, un servicio puede tener un modelado más complejo de los parámetros de entrada. Estos otros tipos, como valores de enumeración y estructuras específicas del servicio, se encuentran en el paquete Go `types` del servicio. 

 Además, los servicios pueden distinguir entre el valor predeterminado de un tipo Go y si el valor lo ha establecido el usuario o no. En estos casos, puede que los parámetros de entrada requieran que pases una referencia del puntero al tipo en cuestión. En el caso de los tipos Go estándar (por ejemplo, numéricos, booleanos y de cadena), existen las funciones prácticas `<Type>` y `From<Type>` disponibles en [aws](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws) para facilitar esta conversión. Por ejemplo, [aws.String](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#String) se puede usar para convertir `string` en un tipo `*string` para los parámetros de entrada que requieren un puntero a una cadena. Por el contrario, [aws.ToString](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#ToString) se puede usar para transformar un elemento `*string` en `string`, al tiempo que se brinda protección frente a la cancelación de referencias a un puntero nulo. Las funciones `To<Type>` son útiles a la hora de gestionar las respuestas del servicio. 

 Veamos un ejemplo de cómo podemos usar un cliente de Amazon S3 para llamar a la API `GetObject` y crear nuestra entrada mediante el paquete `types` y los ayudantes `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,
    })
```

### Reemplazo de opciones de cliente para la llamada a operaciones
<a name="overriding-client-options"></a>

 De forma similar a la que se usa para modificar las opciones de operación de cliente durante la creación de un cliente con argumentos funcionales, las opciones de cliente pueden modificarse en el momento en el que se llama al método de operación al proporcionar uno o varios argumentos funcionales al método de operación de servicio. Esta acción se puede ejecutar a la vez que otras de forma segura y no afectará a otras operaciones simultáneas del cliente. 

 Por ejemplo, para reemplazar la región del cliente “us-west-2” por “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"
    })
```

### Gestión de respuestas de operación
<a name="handling-operation-responses"></a>

 Cada operación de servicio tiene una estructura de salida asociada que contiene los miembros de respuesta de la operación del servicio. La estructura de salida sigue el patrón de nomenclatura `<OperationName>Output`. Puede que algunas operaciones no tengan ningún miembro definido para su salida de operación. Tras llamar a una operación de servicio, siempre se debe comprobar el tipo de argumento `error` devuelto para determinar si se ha producido un error al invocar la operación de servicio. Los errores devueltos pueden abarcar desde errores de validación de entradas del cliente hasta respuestas de error del servicio devueltas al cliente. No se debe acceder a la estructura de salida de la operación en caso de que el cliente devuelva un error que no sea nulo. 

 Por ejemplo, para registrar un error de operación y volver de forma prematura de la función de llamada: 

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

 Para obtener más información sobre la gestión de errores, incluida la forma de inspeccionar tipos de error específicos, consulte TODO. 

#### Respuestas con `io.ReadCloser`
<a name="responses-with-ioreadcloser"></a>

 Algunas operaciones de la API devuelven una estructura de respuesta que contiene un miembro de salida que es `io.ReadCloser`. Este será el caso de las operaciones de la API que expongan algún elemento de su salida en el cuerpo de la propia respuesta HTTP. 

 Por ejemplo, la operación `GetObject` de Amazon S3 devuelve una respuesta cuyo miembro `Body` es un objeto `io.ReadCloser` para acceder a la carga útil del objeto. 

**aviso**  
 SIEMPRE DEBE implementar `Close()` en cualquier miembro de salida `io.ReadCloser`, independientemente de si ha consumido su contenido. De lo contrario, se pueden filtrar recursos y crear posibles problemas al leer los cuerpos de las respuestas en operaciones a las que se llame más adelante. 

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

#### Metadatos de respuesta
<a name="response-metadata"></a>

 Todas las estructuras de salida de las operaciones de servicio incluyen un miembro `ResultMetadata` de tipo [middleware.Metadata](https://pkg.go.dev/github.com/aws/smithy-go/middleware#Metadata). El middleware del SDK utiliza `middleware.Metadata` para proporcionar información adicional a partir de una respuesta del servicio no modelada por este. Esto incluye metadatos como el valor `RequestID`. Por ejemplo, para recuperar el valor `RequestID` asociado a una respuesta del servicio para ayudar a AWS Support a solucionar los problemas de una solicitud: 

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

## Uso simultáneo de clientes de servicio
<a name="concurrently-using-service-clients"></a>

 Puede crear rutinas de Go que utilicen el mismo cliente de servicio de forma simultánea para enviar varias solicitudes. Un cliente de servicio se puede usar con tantas rutinas de Go como desee. 

 En el siguiente ejemplo, se utiliza un cliente de servicio Amazon S3 en varias rutinas de Go. En este ejemplo se cargan dos objetos en un bucket de Amazon S3 de forma simultánea. 

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

## Uso de paginadores de operaciones
<a name="using-operation-paginators"></a>

 Por lo general, al recuperar una lista de elementos, es posible que tenga que comprobar la estructura de salida en busca de un token o marcador para confirmar si el servicio de AWS ha devuelto todos los resultados de su solicitud. Si el token o marcador está presente, se utiliza para solicitar la siguiente página de resultados. En lugar de administrar estos tokens o marcadores, puede usar los tipos de paginadores disponibles del paquete de servicios. 

 Hay ayudantes de paginadores disponibles para las operaciones de servicio admitidas y los encontrará en el paquete Go del cliente de servicio. A fin de crear un paginador para una operación admitida, utilice la función `New<OperationName>Paginator`. Las funciones de creación de paginadores toman el valor de `Client` del servicio, los parámetros de entrada `<OperationName>Input` de la operación y un conjunto opcional de argumentos funcionales que permiten configurar otros ajustes opcionales del paginador. 

 El tipo de paginador de operaciones devuelto ofrece una forma cómoda de recorrer en iteración una operación paginada hasta que llegue a la última página o encuentre los elementos que buscaba la aplicación. Un tipo de paginador tiene dos métodos: `HasMorePages` y `NextPage`. `HasMorePages` devuelve un valor booleano de `true` si no se ha recuperado la primera página o si hay páginas adicionales disponibles para su recuperación mediante la operación. Para recuperar la primera página de la operación o páginas posteriores, se debe llamar a la operación `NextPage`. `NextPage` toma `context.Context` y devuelve la salida de la operación y cualquier error correspondiente. Del mismo modo que se hace con los parámetros devueltos del método de operación de cliente, el error devuelto debe comprobarse siempre antes de intentar usar la estructura de respuesta devuelta. Consulte [Gestión de respuestas de operación](#handling-operation-responses). 

 En el siguiente ejemplo se utiliza el paginador `ListObjectsV2` para enumerar hasta tres páginas de claves de objeto de la operación `ListObjectV2`. Cada página consta de un máximo de diez claves, que se define mediante la opción de paginador `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++
    }
```

 Al igual que sucede con el método de operación de cliente, se pueden modificar opciones de cliente como la región de la solicitud. Para ello, se proporcionan uno o varios argumentos funcionales a `NextPage`. Para obtener más información sobre cómo reemplazar las opciones de cliente al llamar a una operación, consulte [Reemplazo de opciones de cliente para la llamada a operaciones](#overriding-client-options). 

## Uso de esperadores
<a name="using-waiters"></a>

 Al interactuar con las API de AWS que son asíncronas, a menudo es necesario esperar a que un recurso concreto esté disponible para poder realizar más acciones en este. 

 Por ejemplo, la API `CreateTable` de Amazon DynamoDB devuelve una respuesta inmediata con el valor CREATING para TableStatus y el usuario no puede invocar operaciones de lectura o escritura hasta que el estado de la tabla haya cambiado a `ACTIVE`. 

 Escribir lógica para sondear continuamente el estado de la tabla puede resultar engorroso y aumentar la probabilidad de errores. Los esperadores contribuyen a simplificar este proceso y son API sencillas que gestionan la tarea de sondeo de forma automática. 

 Por ejemplo, puede utilizar esperadores para sondear si se ha creado una tabla de DynamoDB y si está lista para una operación de escritura. 

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

### Reemplazo de la configuración de un esperador
<a name="overriding-waiter-configuration"></a>

 De forma predeterminada, el SDK utiliza el valor de retraso mínimo y retraso máximo configurado con valores óptimos definidos por los servicios de AWS para diferentes API. Puede reemplazar la configuración del esperador; para ello, proporcione opciones funcionales durante el proceso de creación de este o al invocar una operación de esperador. 

 Por ejemplo, para reemplazar la configuración del esperador durante el proceso de creación de este: 

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

La función `Wait` de cada esperador también incluye opciones funcionales. Al igual que en el ejemplo anterior, puede reemplazar la configuración del esperador por solicitud `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")
```

### Reemplazo avanzado de la configuración de un esperador
<a name="advanced-waiter-configuration-overrides"></a>

 También puede personalizar el comportamiento predeterminado del esperador mediante una función reintentable personalizada. Las opciones específicas del esperador también proporcionan `APIOptions` para [personalizar los middlewares de las operaciones](middleware.md#writing-a-custom-middleware). 

 Por ejemplo, para configurar reemplazos avanzados del esperador: 

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