

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Driver Amazon QLDB para Go
<a name="getting-started.golang"></a>

**Importante**  
Aviso de fim do suporte: os clientes existentes poderão usar o Amazon QLDB até o final do suporte em 31/07/2025. Para obter mais detalhes, consulte [Migrar um Amazon QLDB Ledger para o Amazon](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/) Aurora PostgreSQL.

Para trabalhar com dados em seu livro contábil, você pode se conectar ao Amazon QLDB a partir do seu aplicativo Go usando um driver fornecido. AWS Os tópicos a seguir descrevem como começar a usar o driver QLDB para Go.

**Topics**
+ [Recursos para driver](#getting-started.golang.resources)
+ [Pré-requisitos](#getting-started.golang.prereqs)
+ [Instalação](#getting-started.golang.install)
+ [Tutorial de início rápido](driver-quickstart-golang.md)
+ [Referência de Cookbook](driver-cookbook-golang.md)

## Recursos para driver
<a name="getting-started.golang.resources"></a>

Para obter mais informações sobre a funcionalidade suportada pelo driver Go, consulte os recursos a seguir:
+ Referência de API: [3.x](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver), [2.x](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver), [1.x](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/qldbdriver)
+ [Código-fonte do driver (GitHub)](https://github.com/awslabs/amazon-qldb-driver-go)
+ [Cookbook Amazon Ion](http://amzn.github.io/ion-docs/guides/cookbook.html)

## Pré-requisitos
<a name="getting-started.golang.prereqs"></a>

Antes de começar a usar o driver QLDB para Go, você deverá fazer o seguinte:

1. Siga as instruções AWS de configuração em[Acessar o Amazon QLDB](accessing.md). Essa transmissão inclui o seguinte:

   1. Inscreva-se em AWS.

   1. Crie um usuário com as permissões adequadas para QLDB.

   1. Conceda acesso programático para desenvolvimento.

1. (Opcional) Instale um ambiente de desenvolvimento integrado (IDE) de sua escolha. Para obter uma lista dos mais usados IDEs para Go, consulte [Plug-ins do Editor e IDEs](https://golang.org/doc/editors.html) no site Go.

1. Baixe e instale uma das seguintes versões do Go no [site de downloads do Go](https://golang.org/dl/):
   + **1.15 ou posterior **: driver QLDB para Go v3
   + **1.14**: driver QLDB para Go v1 ou v2

1. Configure seu ambiente de desenvolvimento para [AWS SDK para Go](https://aws.amazon.com/sdk-for-go).

   1. Configure suas AWS credenciais. Recomendamos criar um arquivo de credenciais compartilhadas.

      Para obter instruções, consulte [Especificação de credenciais](https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/#specifying-credentials) no *Guia do desenvolvedor do AWS SDK para Go *.

   1. Defina sua Região da AWS padrão. Para saber como, consulte [Especificando Região da AWS](https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/#specifying-the-aws-region).

      Para obter uma lista completa das regiões disponíveis, consulte [endpoints e cotas Amazon QLDB](https://docs.aws.amazon.com/general/latest/gr/qldb.html) em *Referência geral da AWS*.

Em seguida, você pode configurar um aplicativo de exemplo básico e executar exemplos de códigos curtos, ou você pode instalar o driver em um projeto Go existente.
+ Para instalar o driver QLDB e AWS SDK para Go o em um projeto existente, vá para. [Instalação](#getting-started.golang.install)
+ Para configurar um projeto e executar exemplos de códigos curtos que demonstram transações básicas de dados em um ledger, consulte o [Tutorial de início rápido](driver-quickstart-golang.md).

## Instalação
<a name="getting-started.golang.install"></a>

[O driver QLDB para Go é de código aberto no GitHub repositório awslabs/. amazon-qldb-driver-go](http://github.com/awslabs/amazon-qldb-driver-go) O QLDB suporta as seguintes versões do driver e suas dependências Go.


****  

| Versão do driver | Versão Go | Status | Data da versão mais recente | 
| --- | --- | --- | --- | 
| [1.x](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/qldbdriver) | 1.14 ou posterior | Lançamento de produção | 16 de junho de 2021 | 
| [2.x](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver) | 1.14 ou posterior | Lançamento de produção | 21 de julho de 2021 | 
| [3.x](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver) | 1.15 ou posterior | Lançamento de produção | 10 de novembro de 2022 | 

**Para instalar o driver**

1. Certifique-se de que seu projeto esteja usando [módulos Go](https://blog.golang.org/using-go-modules) para instalar as dependências do projeto.

1. No diretório do seu projeto, insira o seguinte comando `go get`.

------
#### [ 3.x ]

   ```
   $ go get -u github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver
   ```

------
#### [ 2.x ]

   ```
   $ go get -u github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver
   ```

------

A instalação do driver também instala suas dependências, incluindo [AWS SDK para Go](https://github.com/aws/aws-sdk-go) ou [AWS SDK para Go v2](https://github.com/aws/aws-sdk-go-v2) e os pacotes e [Amazon Ion](https://github.com/amzn/ion-go).

Para exemplos de código curto de como executar transações básicas de dados em um ledger, consulte o [Referência de Cookbook](driver-cookbook-golang.md).

# Driver Amazon QLDB para Go: tutorial de início rápido
<a name="driver-quickstart-golang"></a>

**Importante**  
Aviso de fim do suporte: os clientes existentes poderão usar o Amazon QLDB até o final do suporte em 31/07/2025. Para obter mais detalhes, consulte [Migrar um Amazon QLDB Ledger para o Amazon](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/) Aurora PostgreSQL.

Neste tutorial, você aprenderá como configurar um aplicativo simples usando a versão mais recente do driver QLDB da Amazon para Go. Este guia inclui etapas para instalação do driver e exemplos de códigos curtos de operações básicas de *criação, leitura, atualização e exclusão* (CRUD).

**Topics**
+ [Pré-requisitos](#driver-quickstart-golang.prereqs)
+ [Etapa 1: Instalar o driver](#driver-quickstart-golang.install)
+ [Etapa 2: Importar os pacotes](#driver-quickstart-golang.import)
+ [Etapa 3: Inicializar o driver](#driver-quickstart-golang.initialize)
+ [Etapa 4: Crie uma tabela e um índice](#driver-quickstart-golang.create-table-index)
+ [Etapa 5: Inserir um documento](#driver-quickstart-golang.insert)
+ [Etapa 6: consultar o documento](#driver-quickstart-golang.query)
+ [Etapa 7: Atualize o documento](#driver-quickstart-golang.update)
+ [Etapa 8: consultar o documento atualizado](#driver-quickstart-golang.query-2)
+ [Etapa 9: Descartar a tabela](#driver-quickstart-golang.drop-table)
+ [Executar o aplicativo completo](#driver-quickstart-golang.complete)

## Pré-requisitos
<a name="driver-quickstart-golang.prereqs"></a>

Antes de iniciar, certifique-se de fazer o seguinte:

1. Complete a [Pré-requisitos](getting-started.golang.md#getting-started.golang.prereqs) para o driver Go, caso ainda não o tenha feito. Isso inclui se inscrever AWS, conceder acesso programático para desenvolvimento e instalar o Go.

1. Crie um ledger chamado `quick-start`.

   Para saber como criar um ledger, consulte [Operações básicas para ledgers do Amazon QLDB](ledger-management.basics.md) ou [Etapa 1: criar um novo ledger](getting-started-step-1.md) em *Conceitos básicos do console*.

## Etapa 1: Instalar o driver
<a name="driver-quickstart-golang.install"></a>

Certifique-se de que seu projeto esteja usando [módulos Go](https://blog.golang.org/using-go-modules) para instalar as dependências do projeto.

No diretório do seu projeto, insira o seguinte comando `go get`.

```
$ go get -u github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver
```

A instalação do driver também instala suas dependências, incluindo os pacotes [AWS SDK para Go v2](https://github.com/aws/aws-sdk-go-v2) e [Amazon Ion](https://github.com/amzn/ion-go).

## Etapa 2: Importar os pacotes
<a name="driver-quickstart-golang.import"></a>

Importe os seguintes AWS pacotes.

```
import (
    "context"
    "fmt"

    "github.com/amzn/ion-go/ion"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/qldbSession"
    "github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver"
)
```

## Etapa 3: Inicializar o driver
<a name="driver-quickstart-golang.initialize"></a>

Inicialize uma instância do driver que se conecta ao ledger chamado `quick-start`.

```
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
  panic(err)
}

qldbSession := qldbsession.NewFromConfig(cfg, func(options *qldbsession.Options) {
    options.Region = "us-east-1"
})
driver, err := qldbdriver.New(
    "quick-start",
    qldbSession,
    func(options *qldbdriver.DriverOptions) {
        options.LoggerVerbosity = qldbdriver.LogInfo
    })
if err != nil {
    panic(err)
}

defer driver.Shutdown(context.Background())
```

**nota**  
Neste exemplo de código, *us-east-1* substitua pelo Região da AWS local em que você criou seu livro contábil.

## Etapa 4: Crie uma tabela e um índice
<a name="driver-quickstart-golang.create-table-index"></a>

O exemplo de código a seguir mostra como executar as instruções `CREATE TABLE` e `CREATE INDEX`.

```
_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    _, err := txn.Execute("CREATE TABLE People")
    if err != nil {
        return nil, err
    }

    // When working with QLDB, it's recommended to create an index on fields we're filtering on.
    // This reduces the chance of OCC conflict exceptions with large datasets.
    _, err = txn.Execute("CREATE INDEX ON People (firstName)")
    if err != nil {
        return nil, err
    }

    _, err = txn.Execute("CREATE INDEX ON People (age)")
    if err != nil {
        return nil, err
    }

    return nil, nil
})
if err != nil {
    panic(err)
}
```

Esse código adiciona o código a seguir que cria uma tabela chamada `People` e índices para os campos `firstName` e `age` nessa tabela. Os [índices](ql-reference.create-index.md) são necessários para otimizar o desempenho da consulta e ajudar a limitar as exceções de conflitos de [controle de simultaneidade otimista (OCC)](concurrency.md).

## Etapa 5: Inserir um documento
<a name="driver-quickstart-golang.insert"></a>

Os exemplos de código a seguir mostram como executar uma instrução `INSERT`. O QLDB suporta a linguagem de consulta [PartiQL](ql-reference.md) (compatível com SQL) e o formato de dados [Amazon Ion](ion.md) (superconjunto de JSON).

### Uso do PartiQL literal
<a name="driver-quickstart-golang.insert.partiql"></a>

O código a seguir insere um documento na tabela `People` usando uma instrução partiQL literal de string.

```
_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    return txn.Execute("INSERT INTO People {'firstName': 'Jane', 'lastName': 'Doe', 'age': 77}")
})
if err != nil {
    panic(err)
}
```

### Uso de tipos de dados Ion
<a name="driver-quickstart-golang.insert.ion"></a>

Semelhante ao [pacote JSON](https://golang.org/pkg/encoding/json/) integrado do Go, você pode organizar e desorganizar tipos de dados Go de e para o Ion.

1. Suponha que você tenha a seguinte estrutura Go, chamada `Person`.

   ```
   type Person struct {
       FirstName string `ion:"firstName"`
       LastName  string `ion:"lastName"`
       Age       int    `ion:"age"`
   }
   ```

1. Crie uma instância de `Person`.

   ```
   person := Person{"John", "Doe", 54}
   ```

   O motorista organiza uma representação de `person` de texto codificada por Ion para você.
**Importante**  
Para que a organização e desorganização funcionem corretamente, os nomes dos campos da estrutura de dados Go devem ser exportados (primeira letra maiúscula).

1. Passe a instância `person` para o método `Execute` da transação.

   ```
   _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
       return txn.Execute("INSERT INTO People ?", person)
   })
   if err != nil {
       panic(err)
   }
   ```

   Este exemplo usa um ponto de interrogação (`?`) como um marcador variável para passar as informações do documento para a instrução. Ao usar marcadores, você deve passar um valor de texto codificado por Ion.
**dica**  
Para inserir vários documentos usando uma única instrução [INSERT](ql-reference.insert.md), você pode passar um parâmetro do tipo [lista](driver-working-with-ion.md#driver-ion-list) para a instrução da seguinte maneira.  

   ```
   // people is a list
   txn.Execute("INSERT INTO People ?", people)
   ```
Você não coloca o marcador variável (`?`) entre colchetes angulares duplos (`<<...>>`) ao passar uma lista. Nas instruções manuais do PartiQL, colchetes angulares duplos denotam uma coleção não ordenada conhecida como *bolsa*.

## Etapa 6: consultar o documento
<a name="driver-quickstart-golang.query"></a>

O exemplo de código a seguir mostra como executar uma instrução `SELECT`.

```
p, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE age = 54")
    if err != nil {
        return nil, err
    }

    // Assume the result is not empty
    hasNext := result.Next(txn)
    if !hasNext && result.Err() != nil {
        return nil, result.Err()
    }

    ionBinary := result.GetCurrentData()

    temp := new(Person)
    err = ion.Unmarshal(ionBinary, temp)
    if err != nil {
        return nil, err
    }

    return *temp, nil
})
if err != nil {
    panic(err)
}

var returnedPerson Person
returnedPerson = p.(Person)

if returnedPerson != person {
    fmt.Print("Queried result does not match inserted struct")
}
```

Este exemplo consulta seu documento a partir da tabela `People`, presume que o conjunto de resultados não está vazio e retorna seu documento a partir do resultado.

## Etapa 7: Atualize o documento
<a name="driver-quickstart-golang.update"></a>

O exemplo de código a seguir mostra como executar uma instrução `UPDATE`.

```
person.Age += 10

_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    return txn.Execute("UPDATE People SET age = ? WHERE firstName = ?", person.Age, person.FirstName)
})
if err != nil {
    panic(err)
}
```

## Etapa 8: consultar o documento atualizado
<a name="driver-quickstart-golang.query-2"></a>

O exemplo de código a seguir consulta a tabela `People` por `firstName` e retorna todos os documentos no conjunto de resultados.

```
p, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE firstName = ?", person.FirstName)
    if err != nil {
        return nil, err
    }

    var people []Person
    for result.Next(txn) {
        ionBinary := result.GetCurrentData()

        temp := new(Person)
        err = ion.Unmarshal(ionBinary, temp)
        if err != nil {
            return nil, err
        }

        people = append(people, *temp)
    }
    if result.Err() != nil {
        return nil, result.Err()
    }

    return people, nil
})
if err != nil {
    panic(err)
}

var people []Person
people = p.([]Person)

updatedPerson := Person{"John", "Doe", 64}
if people[0] != updatedPerson {
    fmt.Print("Queried result does not match updated struct")
}
```

## Etapa 9: Descartar a tabela
<a name="driver-quickstart-golang.drop-table"></a>

O exemplo de código a seguir mostra como executar uma instrução `DROP TABLE`.

```
_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    return txn.Execute("DROP TABLE People")
})
if err != nil {
    panic(err)
}
```

## Executar o aplicativo completo
<a name="driver-quickstart-golang.complete"></a>

O exemplo de código a seguir é a versão completa do aplicativo . Em vez de executar as etapas anteriores individualmente, você também pode copiar e executar esse exemplo de código do início ao fim. Este aplicativo demonstra algumas operações básicas do CRUD no ledger denominado `quick-start`.

**nota**  
Antes de executar esse código, verifique se você ainda não tem uma tabela ativa chamada `People` no ledger `quick-start`.

```
package main

import (
    "context"
    "fmt"

    "github.com/amzn/ion-go/ion"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/qldbsession"
    "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)

func main() {
    awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("us-east-1")))
    qldbSession := qldbsession.New(awsSession)

    driver, err := qldbdriver.New(
        "quick-start",
        qldbSession,
        func(options *qldbdriver.DriverOptions) {
            options.LoggerVerbosity = qldbdriver.LogInfo
        })
    if err != nil {
        panic(err)
    }
    defer driver.Shutdown(context.Background())

    _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
        _, err := txn.Execute("CREATE TABLE People")
        if err != nil {
            return nil, err
        }

        // When working with QLDB, it's recommended to create an index on fields we're filtering on.
        // This reduces the chance of OCC conflict exceptions with large datasets.
        _, err = txn.Execute("CREATE INDEX ON People (firstName)")
        if err != nil {
            return nil, err
        }

        _, err = txn.Execute("CREATE INDEX ON People (age)")
        if err != nil {
            return nil, err
        }

        return nil, nil
    })
    if err != nil {
        panic(err)
    }

    _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
        return txn.Execute("INSERT INTO People {'firstName': 'Jane', 'lastName': 'Doe', 'age': 77}")
    })
    if err != nil {
        panic(err)
    }

    type Person struct {
        FirstName string `ion:"firstName"`
        LastName  string `ion:"lastName"`
        Age       int    `ion:"age"`
    }

    person := Person{"John", "Doe", 54}

    _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
        return txn.Execute("INSERT INTO People ?", person)
    })
    if err != nil {
        panic(err)
    }

    p, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
        result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE age = 54")
        if err != nil {
            return nil, err
        }

        // Assume the result is not empty
        hasNext := result.Next(txn)
        if !hasNext && result.Err() != nil {
            return nil, result.Err()
        }

        ionBinary := result.GetCurrentData()

        temp := new(Person)
        err = ion.Unmarshal(ionBinary, temp)
        if err != nil {
            return nil, err
        }

        return *temp, nil
    })
    if err != nil {
        panic(err)
    }

    var returnedPerson Person
    returnedPerson = p.(Person)

    if returnedPerson != person {
        fmt.Print("Queried result does not match inserted struct")
    }

    person.Age += 10

    _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
        return txn.Execute("UPDATE People SET age = ? WHERE firstName = ?", person.Age, person.FirstName)
    })
    if err != nil {
        panic(err)
    }

    p, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
        result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE firstName = ?", person.FirstName)
        if err != nil {
            return nil, err
        }

        var people []Person
        for result.Next(txn) {
            ionBinary := result.GetCurrentData()

            temp := new(Person)
            err = ion.Unmarshal(ionBinary, temp)
            if err != nil {
                return nil, err
            }

            people = append(people, *temp)
        }
        if result.Err() != nil {
            return nil, result.Err()
        }

        return people, nil
    })
    if err != nil {
        panic(err)
    }

    var people []Person
    people = p.([]Person)

    updatedPerson := Person{"John", "Doe", 64}
    if people[0] != updatedPerson {
        fmt.Print("Queried result does not match updated struct")
    }

    _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
        return txn.Execute("DROP TABLE People")
    })
    if err != nil {
        panic(err)
    }
}
```

# Driver Amazon QLDB para Go — Referência do livro de receitas
<a name="driver-cookbook-golang"></a>

**Importante**  
Aviso de fim do suporte: os clientes existentes poderão usar o Amazon QLDB até o final do suporte em 31/07/2025. Para obter mais detalhes, consulte [Migrar um Amazon QLDB Ledger para o Amazon](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/) Aurora PostgreSQL.

Este guia de referência mostra casos de uso comuns do driver Amazon QLDB para Go. Ele fornece exemplos de código Go que demonstram como usar o driver para executar operações básicas CRUD (*create, read, update, delete*). Também inclui exemplos de código para processamento de dados do Amazon Ion. Além disso, este guia destaca as práticas recomendadas para tornar as transações idempotentes e implantar restrições de exclusividade.

**nota**  
Quando aplicável, alguns casos de uso têm exemplos de código diferentes para cada versão principal com suporte do driver QLDB para Go.

**Contents**
+ [Importação do driver](#cookbook-golang.importing)
+ [Instanciação do driver](#cookbook-golang.instantiating)
+ [Operações de CRUD](#cookbook-golang.crud)
  + [Criar tabelas](#cookbook-golang.crud.creating-tables)
  + [Criar índices](#cookbook-golang.crud.creating-indexes)
  + [Ler documentos](#cookbook-golang.crud.reading)
    + [Usar parâmetros de consulta](#cookbook-golang.reading-using-params)
  + [Inserir documentos](#cookbook-golang.crud.inserting)
    + [Como inserir vários documentos em uma instrução](#cookbook-golang.crud.inserting.multiple)
  + [Como atualizar documentos](#cookbook-golang.crud.updating)
  + [Como excluir documentos](#cookbook-golang.crud.deleting)
  + [Como executar várias instruções em uma transação](#cookbook-golang.crud.multi-statement)
  + [Lógica de novas tentativas](#cookbook-golang.crud.retry-logic)
  + [Implementação de restrições de exclusividade](#cookbook-golang.crud.uniqueness-constraints)
+ [Como trabalhar com o Amazon Ion](#cookbook-golang.ion)
  + [Importar o módulo Ion](#cookbook-golang.ion.import)
  + [Criação de tipos de Ion](#cookbook-golang.ion.creating-types)
  + [Obter binário Ion](#cookbook-golang.ion.getting-binary)
  + [Obter texto Ion](#cookbook-golang.ion.getting-text)

## Importação do driver
<a name="cookbook-golang.importing"></a>

O exemplo de código a seguir importa o driver e outros AWS pacotes necessários.

------
#### [ 3.x ]

```
import (

    "github.com/amzn/ion-go/ion"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/qldbSession"
    "github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver"
)
```

------
#### [ 2.x ]

```
import (

    "github.com/amzn/ion-go/ion"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/qldbsession"
    "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)
```

------

**nota**  
Este exemplo também importa o pacote Amazon Ion (`amzn/ion-go/ion`). Você precisa desse pacote para processar dados de íons ao executar algumas operações de dados nesta referência. Para saber mais, consulte [Como trabalhar com o Amazon Ion](#cookbook-golang.ion).

## Instanciação do driver
<a name="cookbook-golang.instantiating"></a>

O exemplo de código a seguir cria uma instância do driver que se conecta a um nome de ledger especificado em um Região da AWS especificado.

------
#### [ 3.x ]

```
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
    panic(err)
}

qldbSession := qldbsession.NewFromConfig(cfg, func(options *qldbsession.Options) {
    options.Region = "us-east-1"
})
driver, err := qldbdriver.New(
  "vehicle-registration",
  qldbSession,
  func(options *qldbdriver.DriverOptions) {
    options.LoggerVerbosity = qldbdriver.LogInfo
})
if err != nil {
  panic(err)
}

defer driver.Shutdown(context.Background())
```

------
#### [ 2.x ]

```
awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("us-east-1")))
qldbSession := qldbsession.New(awsSession)

driver, err := qldbdriver.New(
  "vehicle-registration",
  qldbSession,
  func(options *qldbdriver.DriverOptions) {
    options.LoggerVerbosity = qldbdriver.LogInfo
  })
if err != nil {
  panic(err)
}
```

------

## Operações de CRUD
<a name="cookbook-golang.crud"></a>

O QLDB *executa operações de criação, leitura, atualização e exclusão* (CRUD) como parte de uma transação.

**Atenção**  
Como prática recomendada, torne suas transações de gravação estritamente idempotentes.

**Tornar as transações idempotentes**

Recomendamos que você torne as transações de gravação idempotentes para evitar efeitos colaterais inesperados no caso de novas tentativas. Uma transação é *idempotente* se puder ser executada várias vezes e produzir resultados idênticos a cada vez.

Por exemplo, considere uma transação que insere um documento em uma tabela chamada `Person`. A transação deve primeiro verificar se o documento já existe ou não na tabela. Sem essa verificação, a tabela pode acabar com documentos duplicados.

Suponha que o QLDB confirme com sucesso a transação no lado do servidor, mas o tempo do cliente expire enquanto espera por uma resposta. Se a transação não for idempotente, o mesmo documento poderá ser inserido mais de uma vez no caso de uma nova tentativa.

**Usar índices para evitar varreduras completas da tabela**

Também recomendamos executar instruções com uma cláusula de predicado `WHERE` usando um operador de *igualdade* em um campo indexado ou em um ID de documento, por exemplo, `WHERE indexedField = 123` ou `WHERE indexedField IN (456, 789)`. Sem essa pesquisa indexada, o QLDB precisa fazer uma varredura de tabela, o que pode levar a tempos limite de transação ou conflitos *otimistas de controle de simultaneidade* (OCC).

Para obter mais informações sobre OCC, consulte [Modelo de simultaneidade do Amazon QLDB](concurrency.md).

**Transações criadas implicitamente**

A função [QLDBDriver.Execute](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#QLDBDriver.Execute) aceita uma função lambda que recebe uma instância de [Transaction](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#Transaction), que você pode usar para executar instruções. A instância de `Transaction` envolve uma transação criada implicitamente.

Você pode executar instruções na função do Lambda usando a função `Transaction.Execute`. O driver confirma implicitamente a transação quando a função do Lambda retorna.

As seções a seguir mostram como executar operações CRUD básicas, especificar a lógica de repetição personalizada e implementar restrições de exclusividade.

**Contents**
+ [Criar tabelas](#cookbook-golang.crud.creating-tables)
+ [Criar índices](#cookbook-golang.crud.creating-indexes)
+ [Ler documentos](#cookbook-golang.crud.reading)
  + [Usar parâmetros de consulta](#cookbook-golang.reading-using-params)
+ [Inserir documentos](#cookbook-golang.crud.inserting)
  + [Como inserir vários documentos em uma instrução](#cookbook-golang.crud.inserting.multiple)
+ [Como atualizar documentos](#cookbook-golang.crud.updating)
+ [Como excluir documentos](#cookbook-golang.crud.deleting)
+ [Como executar várias instruções em uma transação](#cookbook-golang.crud.multi-statement)
+ [Lógica de novas tentativas](#cookbook-golang.crud.retry-logic)
+ [Implementação de restrições de exclusividade](#cookbook-golang.crud.uniqueness-constraints)

### Criar tabelas
<a name="cookbook-golang.crud.creating-tables"></a>

```
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  return txn.Execute("CREATE TABLE Person")
})
```

### Criar índices
<a name="cookbook-golang.crud.creating-indexes"></a>

```
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  return txn.Execute("CREATE INDEX ON Person(GovId)")
})
```

### Ler documentos
<a name="cookbook-golang.crud.reading"></a>

```
var decodedResult map[string]interface{}

// Assumes that Person table has documents as follows:
// { "GovId": "TOYENC486FH", "FirstName": "Brent" }
_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  result, err := txn.Execute("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'")
  if err != nil {
    return nil, err
  }
  for result.Next(txn) {
    ionBinary := result.GetCurrentData()
    err = ion.Unmarshal(ionBinary, &decodedResult)
    if err != nil {
      return nil, err
    }
    fmt.Println(decodedResult) // prints map[GovId: TOYENC486FH FirstName:Brent]
  }
  if result.Err() != nil {
    return nil, result.Err()
  }
  return nil, nil
})
if err != nil {
  panic(err)
}
```

#### Usar parâmetros de consulta
<a name="cookbook-golang.reading-using-params"></a>

O exemplo de código a seguir usa um parâmetro de consulta do tipo nativo.

```
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  return txn.Execute("SELECT * FROM Person WHERE GovId = ?", "TOYENC486FH")
})
if err != nil {
  panic(err)
}
```

O exemplo de código a seguir usa múltiplos parâmetros de consulta.

```
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  return txn.Execute("SELECT * FROM Person WHERE GovId = ? AND FirstName = ?", "TOYENC486FH", "Brent")
})
if err != nil {
  panic(err)
}
```

O exemplo de código a seguir usa uma lista de parâmetros de consulta.

```
govIDs := []string{}{"TOYENC486FH", "ROEE1", "YH844"}

result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  return txn.Execute("SELECT * FROM Person WHERE GovId IN (?,?,?)", govIDs...)
})
if err != nil {
  panic(err)
}
```

**nota**  
Quando você executa uma consulta sem uma pesquisa indexada, ela invoca uma verificação completa da tabela. Neste exemplo, recomendamos ter um [índice](ql-reference.create-index.md) no campo `GovId` para otimizar o desempenho. Sem um índice em `GovId`, as consultas podem ter mais latência e também podem levar a exceções de conflitos de OCC ou a tempos limite de transação.

### Inserir documentos
<a name="cookbook-golang.crud.inserting"></a>

Os exemplos de código a seguir inserem os tipos de dados nativos.

```
_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  // Check if a document with a GovId of TOYENC486FH exists
  // This is critical to make this transaction idempotent
  result, err := txn.Execute("SELECT * FROM Person WHERE GovId = ?", "TOYENC486FH")
  if err != nil {
    return nil, err
  }
  // Check if there are any results
  if result.Next(txn) {
    // Document already exists, no need to insert
  } else {
    person := map[string]interface{}{
      "GovId": "TOYENC486FH",
      "FirstName": "Brent",
    }
    _, err = txn.Execute("INSERT INTO Person ?", person)
    if err != nil {
      return nil, err
    }
  }
  return nil, nil
})
```

Essa transação insere um documento na tabela `Person`. Antes de inserir, ele primeiro verifica se o documento já existe na tabela. **Essa verificação torna a transação idempotente por natureza.** Mesmo que você execute essa transação várias vezes, ela não causará efeitos colaterais indesejados.

**nota**  
Neste exemplo, recomendamos ter um índice no campo `GovId` para otimizar o desempenho. Sem um índice em `GovId`, as instruções podem ter mais latência e também podem levar a exceções de conflitos de OCC ou a tempos limite de transação.

#### Como inserir vários documentos em uma instrução
<a name="cookbook-golang.crud.inserting.multiple"></a>

Para inserir vários documentos usando uma única instrução [INSERT](ql-reference.insert.md), você pode passar um parâmetro do tipo [lista](driver-working-with-ion.md#driver-ion-list) para a instrução da seguinte maneira.

```
// people is a list
txn.Execute("INSERT INTO People ?", people)
```

Você não coloca o marcador variável (`?`) entre colchetes angulares duplos (`<<...>>`) ao passar uma lista. Nas instruções manuais do PartiQL, colchetes angulares duplos denotam uma coleção não ordenada conhecida como *bolsa*.

### Como atualizar documentos
<a name="cookbook-golang.crud.updating"></a>

Os exemplos de código a seguir usam tipos de dados nativos.

```
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  return txn.Execute("UPDATE Person SET FirstName = ? WHERE GovId = ?", "John", "TOYENC486FH")
})
```

**nota**  
Neste exemplo, recomendamos ter um índice no campo `GovId` para otimizar o desempenho. Sem um índice em `GovId`, as instruções podem ter mais latência e também podem levar a exceções de conflitos de OCC ou a tempos limite de transação.

### Como excluir documentos
<a name="cookbook-golang.crud.deleting"></a>

Os exemplos de código a seguir usam tipos de dados nativos.

```
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  return txn.Execute("DELETE FROM Person WHERE GovId = ?", "TOYENC486FH")
})
```

**nota**  
Neste exemplo, recomendamos ter um índice no campo `GovId` para otimizar o desempenho. Sem um índice em `GovId`, as instruções podem ter mais latência e também podem levar a exceções de conflitos de OCC ou a tempos limite de transação.

### Como executar várias instruções em uma transação
<a name="cookbook-golang.crud.multi-statement"></a>

```
// This code snippet is intentionally trivial. In reality you wouldn't do this because you'd
// set your UPDATE to filter on vin and insured, and check if you updated something or not.
func InsureCar(driver *qldbdriver.QLDBDriver, vin string) (bool, error) {
    insured, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {

        result, err := txn.Execute(
            "SELECT insured FROM Vehicles WHERE vin = ? AND insured = FALSE", vin)
        if err != nil {
            return false, err
        }

        hasNext := result.Next(txn)
        if !hasNext && result.Err() != nil {
            return false, result.Err()
        }

        if hasNext {
            _, err = txn.Execute(
                "UPDATE Vehicles SET insured = TRUE WHERE vin = ?", vin)
            if err != nil {
                return false, err
            }
            return true, nil
        }
        return false, nil
    })
    if err != nil {
        panic(err)
    }

    return insured.(bool), err
}
```

### Lógica de novas tentativas
<a name="cookbook-golang.crud.retry-logic"></a>

A funcionalidade `Execute` do driver tem um mecanismo de repetição integrado que repete a transação se ocorrer uma exceção que pode ser repetida (como tempos limite ou conflitos de OCC). O número máximo de tentativas de repetição e a estratégia de recuo são configuráveis.

O limite padrão de repetição é`4`, e a estratégia de recuo padrão é [ExponentialBackoffStrategy](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#ExponentialBackoffStrategy)com uma base de `10` milissegundos. Você pode definir a política de repetição por instância de driver e também por transação usando uma instância de [RetryPolicy](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#RetryPolicy).

O exemplo de código a seguir especifica a lógica de repetição com um limite de repetição personalizado e uma estratégia de recuo personalizada para uma instância do driver.

```
import (
  "github.com/aws/aws-sdk-go/aws"
  "github.com/aws/aws-sdk-go/aws/session"
  "github.com/aws/aws-sdk-go/service/qldbsession"
  "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)

func main() {
  awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("us-east-1")))
  qldbSession := qldbsession.New(awsSession)

  // Configuring retry limit to 2
  retryPolicy := qldbdriver.RetryPolicy{MaxRetryLimit: 2}

  driver, err := qldbdriver.New("test-ledger", qldbSession, func(options *qldbdriver.DriverOptions) {
    options.RetryPolicy = retryPolicy
  })
  if err != nil {
    panic(err)
  }

  // Configuring an exponential backoff strategy with base of 20 milliseconds
  retryPolicy = qldbdriver.RetryPolicy{
    MaxRetryLimit: 2,
    Backoff: qldbdriver.ExponentialBackoffStrategy{SleepBase: 20, SleepCap: 4000,
    }}

  driver, err = qldbdriver.New("test-ledger", qldbSession, func(options *qldbdriver.DriverOptions) {
    options.RetryPolicy = retryPolicy
  })
  if err != nil {
    panic(err)
  }
}
```

O exemplo de código a seguir especifica a lógica de repetição com um limite de repetição personalizado e uma estratégia de recuo personalizada para uma instância anônima particular. A função `SetRetryPolicy` substitui a política de repetição definida para a instância do driver.

```
import (
  "context"
  "github.com/aws/aws-sdk-go/aws"
  "github.com/aws/aws-sdk-go/aws/session"
  "github.com/aws/aws-sdk-go/service/qldbsession"
  "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver"
)

func main() {
  awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("us-east-1")))
  qldbSession := qldbsession.New(awsSession)

  // Configuring retry limit to 2
  retryPolicy1 := qldbdriver.RetryPolicy{MaxRetryLimit: 2}

  driver, err := qldbdriver.New("test-ledger", qldbSession, func(options *qldbdriver.DriverOptions) {
    options.RetryPolicy = retryPolicy1
  })
  if err != nil {
    panic(err)
  }

  // Configuring an exponential backoff strategy with base of 20 milliseconds
  retryPolicy2 := qldbdriver.RetryPolicy{
    MaxRetryLimit: 2,
    Backoff: qldbdriver.ExponentialBackoffStrategy{SleepBase: 20, SleepCap: 4000,
    }}

  // Overrides the retry policy set by the driver instance
  driver.SetRetryPolicy(retryPolicy2)

  driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
    return txn.Execute("CREATE TABLE Person")
  })
}
```

### Implementação de restrições de exclusividade
<a name="cookbook-golang.crud.uniqueness-constraints"></a>

O QLDB não oferece suporte a índices exclusivos, mas você pode implementar esse comportamento em seu aplicativo.

Suponha que você queira implementar uma restrição de exclusividade no campo `GovId` da tabela `Person`. Para fazer isso, você pode escrever uma transação que faça o seguinte:

1. Afirme que a tabela não tem documentos existentes com um `GovId` especificado.

1. Insira o documento se a afirmação for aprovada.

Se uma transação concorrente passar simultaneamente pela declaração, somente uma das transações será confirmada com sucesso. A outra transação falhará com uma exceção de conflito de OCC.

O exemplo de código a seguir mostra como implementar essa lógica de restrição de exclusividade.

```
govID := "TOYENC486FH"

document := map[string]interface{}{
  "GovId":     "TOYENC486FH",
  "FirstName": "Brent",
}

result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) {
  // Check if doc with GovId = govID exists
  result, err := txn.Execute("SELECT * FROM Person WHERE GovId = ?", govID)
  if err != nil {
    return nil, err
  }
  // Check if there are any results
  if result.Next(txn) {
    // Document already exists, no need to insert
    return nil, nil
  }
  return txn.Execute("INSERT INTO Person ?", document)
})
if err != nil {
  panic(err)
}
```

**nota**  
Neste exemplo, recomendamos ter um índice no campo `GovId` para otimizar o desempenho. Sem um índice em `GovId`, as instruções podem ter mais latência e também podem levar a exceções de conflitos de OCC ou a tempos limite de transação.

## Como trabalhar com o Amazon Ion
<a name="cookbook-golang.ion"></a>

As seções a seguir mostram como usar o módulo Amazon Ion para processar dados do Ion.

**Contents**
+ [Importar o módulo Ion](#cookbook-golang.ion.import)
+ [Criação de tipos de Ion](#cookbook-golang.ion.creating-types)
+ [Obter binário Ion](#cookbook-golang.ion.getting-binary)
+ [Obter texto Ion](#cookbook-golang.ion.getting-text)

### Importar o módulo Ion
<a name="cookbook-golang.ion.import"></a>

```
import "github.com/amzn/ion-go/ion"
```

### Criação de tipos de Ion
<a name="cookbook-golang.ion.creating-types"></a>

Atualmente, a biblioteca Ion para Go não oferece suporte ao Document Object Model (DOM), então você não pode criar tipos de dados Ion. Mas você pode organizar e desorganizar entre os tipos nativos de Go e o binário Ion ao trabalhar com o QLDB.

### Obter binário Ion
<a name="cookbook-golang.ion.getting-binary"></a>

```
aDict := map[string]interface{}{
  "GovId": "TOYENC486FH",
  "FirstName": "Brent",
}

ionBytes, err := ion.MarshalBinary(aDict)
if err != nil {
  panic(err)
}

fmt.Println(ionBytes) // prints [224 1 0 234 238 151 129 131 222 147 135 190 144 133 71 111 118 73 100 137 70 105 114 115 116 78 97 109 101 222 148 138 139 84 79 89 69 78 67 52 56 54 70 72 139 133 66 114 101 110 116]
```

### Obter texto Ion
<a name="cookbook-golang.ion.getting-text"></a>

```
aDict := map[string]interface{}{
  "GovId": "TOYENC486FH",
  "FirstName": "Brent",
}

ionBytes, err := ion.MarshalText(aDict)
if err != nil {
  panic(err)
}

fmt.Println(string(ionBytes)) // prints {FirstName:"Brent",GovId:"TOYENC486FH"}
```

Para obter mais informações sobre o Ion, consulte a [documentação do Amazon Ion](http://amzn.github.io/ion-docs/) em GitHub. Para obter mais exemplos de código sobre como trabalhar com o Ion no QLDB, consulte [Como trabalhar com tipos de dados do Amazon Ion no Amazon QLDB](driver-working-with-ion.md).