

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Driver Amazon QLDB per Go: riferimento al libro di cucina
<a name="driver-cookbook-golang"></a>

**Importante**  
Avviso di fine del supporto: i clienti esistenti potranno utilizzare Amazon QLDB fino alla fine del supporto, il 31/07/2025. Per ulteriori dettagli, consulta [Migrare un registro Amazon QLDB su Amazon Aurora PostgreSQL](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/).

Questa guida di riferimento mostra i casi d'uso comuni del driver Amazon QLDB per Go. Fornisce esempi di codice Go che dimostrano come utilizzare il driver per eseguire operazioni di base di *creazione, lettura, aggiornamento ed eliminazione* (CRUD). Include anche esempi di codice per l'elaborazione dei dati di Amazon Ion. Inoltre, questa guida illustra le migliori pratiche per rendere le transazioni idempotenti e implementare vincoli di unicità.

**Nota**  
Ove applicabile, alcuni casi d'uso hanno esempi di codice diversi per ogni versione principale supportata del driver QLDB per Go.

**Contents**
+ [Importazione del driver](#cookbook-golang.importing)
+ [Istanziazione del driver](#cookbook-golang.instantiating)
+ [Operazioni CRUD](#cookbook-golang.crud)
  + [Creazione di tabelle](#cookbook-golang.crud.creating-tables)
  + [Creazione di indici](#cookbook-golang.crud.creating-indexes)
  + [Leggere documenti](#cookbook-golang.crud.reading)
    + [Utilizzo dei parametri di interrogazione](#cookbook-golang.reading-using-params)
  + [Inserimento di documenti](#cookbook-golang.crud.inserting)
    + [Inserimento di più documenti in un'unica dichiarazione](#cookbook-golang.crud.inserting.multiple)
  + [Aggiornamento dei documenti](#cookbook-golang.crud.updating)
  + [Eliminazione di documenti](#cookbook-golang.crud.deleting)
  + [Esecuzione di più istruzioni in una transazione](#cookbook-golang.crud.multi-statement)
  + [Logica di ripetizione dei tentativi](#cookbook-golang.crud.retry-logic)
  + [Implementazione di vincoli di unicità](#cookbook-golang.crud.uniqueness-constraints)
+ [Lavorare con Amazon Ion](#cookbook-golang.ion)
  + [Importazione del modulo Ion](#cookbook-golang.ion.import)
  + [Creazione di tipi di ioni](#cookbook-golang.ion.creating-types)
  + [Ottenere il binario Ion](#cookbook-golang.ion.getting-binary)
  + [Ricevere testo Ion](#cookbook-golang.ion.getting-text)

## Importazione del driver
<a name="cookbook-golang.importing"></a>

Il seguente esempio di codice importa il driver e gli altri AWS pacchetti richiesti.

------
#### [ 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**  
Questo esempio importa anche il pacchetto Amazon Ion (`amzn/ion-go/ion`). Questo pacchetto è necessario per elaborare i dati Ion durante l'esecuzione di alcune operazioni sui dati in questo riferimento. Per ulteriori informazioni, consulta [Lavorare con Amazon Ion](#cookbook-golang.ion).

## Istanziazione del driver
<a name="cookbook-golang.instantiating"></a>

Il seguente esempio di codice crea un'istanza del driver che si connette a un nome di registro specificato in un determinato periodo. Regione AWS

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

------

## Operazioni CRUD
<a name="cookbook-golang.crud"></a>

QLDB *esegue operazioni di creazione, lettura, aggiornamento ed* eliminazione (CRUD) come parte di una transazione.

**avvertimento**  
Come best practice, rendi le tue transazioni di scrittura strettamente idempotenti.

**Rendere le transazioni idempotenti**

Si consiglia di rendere le transazioni di scrittura idempotenti per evitare effetti collaterali imprevisti in caso di nuovi tentativi. Una transazione è *idempotente* se può essere eseguita più volte e produrre risultati identici ogni volta.

Ad esempio, si consideri una transazione che inserisce un documento in una tabella denominata. `Person` La transazione deve innanzitutto verificare se il documento esiste già o meno nella tabella. Senza questo controllo, la tabella potrebbe finire con documenti duplicati.

Supponiamo che QLDB esegua correttamente il commit della transazione sul lato server, ma che il client scada in attesa di una risposta. Se la transazione non è idempotente, lo stesso documento potrebbe essere inserito più di una volta in caso di nuovo tentativo.

**Utilizzo degli indici per evitare scansioni complete della tabella**

Si consiglia inoltre di eseguire istruzioni con una clausola di `WHERE` predicato utilizzando un operatore di *uguaglianza* su un campo indicizzato o un ID di documento, ad esempio o. `WHERE indexedField = 123` `WHERE indexedField IN (456, 789)` *Senza questa ricerca indicizzata, QLDB deve eseguire una scansione della tabella, che può portare a timeout delle transazioni o conflitti ottimistici di controllo della concorrenza (OCC).*

[Modello di concorrenza Amazon QLDB](concurrency.md)Per ulteriori informazioni su OCC, vedere.

**Transazioni create implicitamente**

La funzione [QLDBDriver.Execute](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#QLDBDriver.Execute) accetta una funzione lambda che riceve un'istanza di [Transaction](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#Transaction), che è possibile utilizzare per eseguire istruzioni. L'istanza di include una `Transaction` transazione creata implicitamente.

È possibile eseguire istruzioni all'interno della funzione lambda utilizzando la funzione. `Transaction.Execute` Il driver esegue implicitamente la transazione quando ritorna la funzione lambda.

Le sezioni seguenti mostrano come eseguire operazioni CRUD di base, specificare una logica di ripetizione personalizzata e implementare vincoli di unicità.

**Contents**
+ [Creazione di tabelle](#cookbook-golang.crud.creating-tables)
+ [Creazione di indici](#cookbook-golang.crud.creating-indexes)
+ [Leggere documenti](#cookbook-golang.crud.reading)
  + [Utilizzo dei parametri di interrogazione](#cookbook-golang.reading-using-params)
+ [Inserimento di documenti](#cookbook-golang.crud.inserting)
  + [Inserimento di più documenti in un'unica dichiarazione](#cookbook-golang.crud.inserting.multiple)
+ [Aggiornamento dei documenti](#cookbook-golang.crud.updating)
+ [Eliminazione di documenti](#cookbook-golang.crud.deleting)
+ [Esecuzione di più istruzioni in una transazione](#cookbook-golang.crud.multi-statement)
+ [Logica di ripetizione dei tentativi](#cookbook-golang.crud.retry-logic)
+ [Implementazione di vincoli di unicità](#cookbook-golang.crud.uniqueness-constraints)

### Creazione di tabelle
<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")
})
```

### Creazione di indici
<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)")
})
```

### Leggere documenti
<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)
}
```

#### Utilizzo dei parametri di interrogazione
<a name="cookbook-golang.reading-using-params"></a>

Il seguente esempio di codice utilizza un parametro di query di 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)
}
```

Il seguente esempio di codice utilizza più parametri di query.

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

Il seguente esempio di codice utilizza un elenco di parametri di query.

```
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 si esegue una query senza una ricerca indicizzata, viene richiamata una scansione completa della tabella. In questo esempio, si consiglia di disporre di un [indice](ql-reference.create-index.md) sul campo per ottimizzare le `GovId` prestazioni. Senza un indice attivo`GovId`, le query possono avere una maggiore latenza e possono anche portare a eccezioni nei conflitti OCC o a timeout delle transazioni.

### Inserimento di documenti
<a name="cookbook-golang.crud.inserting"></a>

Il seguente esempio di codice inserisce tipi di dati nativi.

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

Questa transazione inserisce un documento nella `Person` tabella. Prima dell'inserimento, controlla innanzitutto se il documento esiste già nella tabella. **Questo controllo rende la transazione di natura idempotente.** Anche se esegui questa transazione più volte, non causerà effetti collaterali indesiderati.

**Nota**  
In questo esempio, consigliamo di avere un indice sul `GovId` campo per ottimizzare le prestazioni. Senza un indice attivo`GovId`, le istruzioni possono avere una maggiore latenza e possono anche portare a eccezioni nei conflitti OCC o a timeout delle transazioni.

#### Inserimento di più documenti in un'unica dichiarazione
<a name="cookbook-golang.crud.inserting.multiple"></a>

Per inserire più documenti utilizzando una singola [INSERT](ql-reference.insert.md) istruzione, è possibile passare un parametro di tipo [elenco](driver-working-with-ion.md#driver-ion-list) all'istruzione come segue.

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

Non racchiudete la variabile placeholder (`?`) tra parentesi angolari doppie (`<<...>>`) quando passate un elenco. *Nelle istruzioni PartiQL manuali, le parentesi doppie angolari indicano una raccolta non ordinata nota come borsa.*

### Aggiornamento dei documenti
<a name="cookbook-golang.crud.updating"></a>

Il seguente esempio di codice utilizza tipi di dati nativi.

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

**Nota**  
In questo esempio, si consiglia di disporre di un indice sul `GovId` campo per ottimizzare le prestazioni. Senza un indice attivo`GovId`, le istruzioni possono avere una maggiore latenza e possono anche portare a eccezioni nei conflitti OCC o a timeout delle transazioni.

### Eliminazione di documenti
<a name="cookbook-golang.crud.deleting"></a>

Il seguente esempio di codice utilizza tipi di dati nativi.

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

**Nota**  
In questo esempio, si consiglia di disporre di un indice sul `GovId` campo per ottimizzare le prestazioni. Senza un indice attivo`GovId`, le istruzioni possono avere una maggiore latenza e possono anche portare a eccezioni nei conflitti OCC o a timeout delle transazioni.

### Esecuzione di più istruzioni in una transazione
<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
}
```

### Logica di ripetizione dei tentativi
<a name="cookbook-golang.crud.retry-logic"></a>

La `Execute` funzione del driver dispone di un meccanismo di riprova integrato che riprova la transazione se si verifica un'eccezione riprovabile (ad esempio in caso di timeout o conflitti OCC). Il numero massimo di tentativi di nuovo tentativo e la strategia di backoff sono configurabili.

Il limite di tentativi predefinito è`4`, e la strategia di backoff predefinita è [ExponentialBackoffStrategy](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#ExponentialBackoffStrategy)con una base di millisecondi. `10` È possibile impostare la politica di riprova per istanza del driver e anche per transazione utilizzando un'istanza di. [RetryPolicy](https://pkg.go.dev/github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver#RetryPolicy)

Il seguente esempio di codice specifica la logica di ripetizione con un limite di tentativi personalizzato e una strategia di backoff personalizzata per un'istanza del 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)
  }
}
```

Il seguente esempio di codice specifica la logica dei tentativi con un limite di tentativi personalizzato e una strategia di backoff personalizzata per una particolare funzione anonima. La `SetRetryPolicy` funzione sostituisce la politica di riprova impostata per l'istanza del 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")
  })
}
```

### Implementazione di vincoli di unicità
<a name="cookbook-golang.crud.uniqueness-constraints"></a>

QLDB non supporta indici univoci, ma puoi implementare questo comportamento nella tua applicazione.

Supponiamo di voler implementare un vincolo di unicità sul campo della tabella. `GovId` `Person` A tale scopo, è possibile scrivere una transazione che esegua le seguenti operazioni:

1. Asserisce che la tabella non ha documenti esistenti con un valore specificato`GovId`.

1. Inserisci il documento se l'asserzione ha esito positivo.

Se una transazione concorrente supera contemporaneamente l'asserzione, solo una delle transazioni verrà salvata correttamente. L'altra transazione avrà esito negativo con un'eccezione relativa al conflitto OCC.

Il seguente esempio di codice mostra come implementare questa logica di vincolo di unicità.

```
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**  
In questo esempio, si consiglia di disporre di un indice sul `GovId` campo per ottimizzare le prestazioni. Senza un indice attivo`GovId`, le istruzioni possono avere una maggiore latenza e possono anche portare a eccezioni nei conflitti OCC o a timeout delle transazioni.

## Lavorare con Amazon Ion
<a name="cookbook-golang.ion"></a>

Le seguenti sezioni mostrano come utilizzare il modulo Amazon Ion per elaborare i dati Ion.

**Contents**
+ [Importazione del modulo Ion](#cookbook-golang.ion.import)
+ [Creazione di tipi di ioni](#cookbook-golang.ion.creating-types)
+ [Ottenere il binario Ion](#cookbook-golang.ion.getting-binary)
+ [Ricevere testo Ion](#cookbook-golang.ion.getting-text)

### Importazione del modulo Ion
<a name="cookbook-golang.ion.import"></a>

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

### Creazione di tipi di ioni
<a name="cookbook-golang.ion.creating-types"></a>

La libreria Ion per Go attualmente non supporta il Document Object Model (DOM), quindi non puoi creare tipi di dati Ion. Ma puoi eseguire il marshal e il unmarshal tra i tipi nativi Go e il binario Ion quando lavori con QLDB.

### Ottenere il binario 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]
```

### Ricevere testo 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"}
```

Per ulteriori informazioni su Ion, consulta la [documentazione di Amazon Ion](http://amzn.github.io/ion-docs/) su GitHub. Per altri esempi di codice sull'utilizzo di Ion in QLDB, vedere. [Utilizzo dei tipi di dati Amazon Ion in Amazon QLDB](driver-working-with-ion.md)