

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

# Definisci i gestori di funzioni Lambda in Go
<a name="golang-handler"></a>

Il *gestore* di funzioni Lambda è il metodo nel codice della funzione che elabora gli eventi. Quando viene richiamata la funzione, Lambda esegue il metodo del gestore. La funzione viene eseguita fino a quando il gestore non restituisce una risposta, termina o scade.

Questa pagina descrive come lavorare con i gestori di funzioni Lambda in Go, inclusa la configurazione del progetto, le convenzioni di denominazione e le migliori pratiche. Questa pagina include anche un esempio di funzione Go Lambda che raccoglie informazioni su un ordine, produce una ricevuta in un file di testo e inserisce questo file in un bucket Amazon Simple Storage Service (S3). Per informazioni su come distribuire una funzione dopo averla scritta, consulta o. [Distribuisci funzioni Lambda per Go con gli archivi di file .zip](golang-package.md) [Distribuzione delle funzioni Go Lambda con immagini di container](go-image.md)

**Topics**
+ [Configurazione di Go Handler](#golang-handler-setup)
+ [Esempio di codice della funzione Lambda](#golang-example-code)
+ [Convenzioni di denominazione dei gestori](#golang-handler-naming)
+ [Definizione e accesso all'oggetto evento di input](#golang-example-input)
+ [Accesso e utilizzo dell'oggetto contestuale Lambda](#golang-example-context)
+ [Firme dell'handler valide per gli handler Go](#golang-handler-signatures)
+ [Utilizzo della AWS SDK per Go versione v2 nell'handler](#golang-example-sdk-usage)
+ [Accesso alle variabili d'ambiente](#golang-example-envvars)
+ [Utilizzo dello stato globale](#golang-handler-state)
+ [Procedure consigliate di codice per le funzioni Go Lambda](#go-best-practices)

## Configurazione di Go Handler
<a name="golang-handler-setup"></a>

Una funzione Lambda scritta in [Go](https://golang.org/) viene creata come eseguibile di Go. È possibile inizializzare un progetto di funzione Go Lambda nello stesso modo in cui inizializzi qualsiasi altro progetto Go utilizzando il seguente comando: `go mod init`

```
go mod init example-go
```

Ecco il nome del `example-go` modulo. Puoi sostituire con un valore qualsiasi. Questo comando inizializza il progetto e genera il `go.mod` file che elenca le dipendenze del progetto.

Utilizzate il `go get` comando per aggiungere eventuali dipendenze esterne al progetto. Nel codice della funzione Lambda è necessario includere il pacchetto [github.com/aws/aws-lambda-go/lambda](https://github.com/aws/aws-lambda-go/tree/master/lambda) che implementa il modello di programmazione Lambda per Go. Installa il pacchetto con il seguente comando `go get`:

```
go get github.com/aws/aws-lambda-go
```

Il codice della funzione dovrebbe risiedere in un file Go. In questo esempio viene assegnato un nome a questo file`main.go`. In questo file, implementa la logica della funzione principale in un metodo di gestione, oltre a una funzione `main()` che chiama questo handler.

## Esempio di codice della funzione Lambda
<a name="golang-example-code"></a>

Il seguente esempio di codice della funzione Go Lambda raccoglie le informazioni su un ordine, produce una ricevuta in un file di testo e inserisce questo file in un bucket Amazon S3.

**Example Funzione Lambda `main.go`**  

```
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

type Order struct {
	OrderID string  `json:"order_id"`
	Amount  float64 `json:"amount"`
	Item    string  `json:"item"`
}

var (
	s3Client *s3.Client
)

func init() {
	// Initialize the S3 client outside of the handler, during the init phase
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		log.Fatalf("unable to load SDK config, %v", err)
	}

	s3Client = s3.NewFromConfig(cfg)
}

func uploadReceiptToS3(ctx context.Context, bucketName, key, receiptContent string) error {
	_, err := s3Client.PutObject(ctx, &s3.PutObjectInput{
		Bucket: &bucketName,
		Key:    &key,
		Body:   strings.NewReader(receiptContent),
	})
	if err != nil {
		log.Printf("Failed to upload receipt to S3: %v", err)
		return err
	}
	return nil
}

func handleRequest(ctx context.Context, event json.RawMessage) error {
	// Parse the input event
	var order Order
	if err := json.Unmarshal(event, &order); err != nil {
		log.Printf("Failed to unmarshal event: %v", err)
		return err
	}

	// Access environment variables
	bucketName := os.Getenv("RECEIPT_BUCKET")
	if bucketName == "" {
		log.Printf("RECEIPT_BUCKET environment variable is not set")
		return fmt.Errorf("missing required environment variable RECEIPT_BUCKET")
	}

	// Create the receipt content and key destination
	receiptContent := fmt.Sprintf("OrderID: %s\nAmount: $%.2f\nItem: %s",
		order.OrderID, order.Amount, order.Item)
	key := "receipts/" + order.OrderID + ".txt"

	// Upload the receipt to S3 using the helper method
	if err := uploadReceiptToS3(ctx, bucketName, key, receiptContent); err != nil {
		return err
	}

	log.Printf("Successfully processed order %s and stored receipt in S3 bucket %s", order.OrderID, bucketName)
	return nil
}

func main() {
	lambda.Start(handleRequest)
}
```

Questo file `main.go` contiene le sezioni seguenti:
+ `package main`: in Go, il pacchetto contenente la funzione `func main()` deve essere sempre denominato `main`.
+ Blocco `import`: utilizza questo blocco per includere le librerie richieste dalla funzione Lambda.
+ `type Order struct {}`block: definisce la forma dell'evento di input previsto in questa struttura Go.
+ `var ()`block: usa questo blocco per definire tutte le variabili globali che utilizzerai nella tua funzione Lambda.
+ `func init() {}`: includi in questo metodo qualsiasi codice che desideri che Lambda esegua durante la [fase di inizializzazione](lambda-runtime-environment.md#runtimes-lifecycle-ib). `init()`
+ `func uploadReceiptToS3(...) {}`: questo è un metodo helper a cui fa riferimento il metodo dell'handler principale `handleRequest`.
+ `func handleRequest(ctx context.Context, event json.RawMessage) error {}`: questo è il **metodo dell'handler principale**, che contiene la logica principale dell'applicazione.
+ `func main() {}`: questo è un punto di ingresso obbligatorio per il tuo handler Lambda. L'argomento del metodo `lambda.Start()` è il metodo principale dell'handler.

Affinché questa funzione funzioni correttamente, il suo [ruolo di esecuzione](lambda-intro-execution-role.md) deve consentire l'`s3:PutObject`azione. Inoltre, assicuratevi di definire la variabile di `RECEIPT_BUCKET` ambiente. Dopo una chiamata riuscita, il bucket Amazon S3 dovrebbe contenere un file di ricevuta.

## Convenzioni di denominazione dei gestori
<a name="golang-handler-naming"></a>

Per le funzioni Lambda in Go, puoi usare qualsiasi nome per l'handler. In questo esempio, il nome del metodo dell'handler è `handleRequest`. Per fare riferimento al valore del gestore nel codice, puoi usare la variabile di ambiente `_HANDLER`.

Per le funzioni Go implementate mediante un [pacchetto di implementazione .zip](golang-package.md), il file eseguibile che contiene il codice della funzione deve essere denominato `bootstrap`. Il file `bootstrap` deve trovarsi nella posizione root del file .zip. Per le funzioni Go implementate mediante una [immagine del container](go-image.md#go-image-provided), per il file eseguibile è possibile usare qualsiasi nome.

## Definizione e accesso all'oggetto evento di input
<a name="golang-example-input"></a>

JSON è il formato di input più comune e standard per le funzioni Lambda. In questo esempio, la funzione prevede un input simile a quanto segue:

```
{
    "order_id": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

Quando si utilizzano le funzioni Lambda in Go, è possibile definire la forma dell'evento di input previsto come struttura Go. In questo esempio, definiamo una struttura per rappresentare un`Order`:

```
type Order struct {
    OrderID string  `json:"order_id"`
    Amount  float64 `json:"amount"`
    Item    string  `json:"item"`
}
```

Questa struttura corrisponde alla forma di input prevista. Dopo aver definito la struttura, puoi scrivere una firma dell'handler che includa un tipo JSON generico compatibile con la libreria standard [encoding/json](https://pkg.go.dev/encoding/json). [Puoi quindi deserializzarlo nella tua struttura usando la funzione func Unmarshal.](https://golang.org/pkg/encoding/json/#Unmarshal) Ciò è illustrato nelle prime righe dell'handler:

```
func handleRequest(ctx context.Context, event json.RawMessage) error {
    // Parse the input event
    var order Order
    if err := json.Unmarshal(event, &order); err != nil {
        log.Printf("Failed to unmarshal event: %v", err)
        return err
    ...
}
```

Dopo questa deserializzazione, è possibile accedere ai campi della variabile. `order` Ad esempio, `order.OrderID` recupera il valore di `"order_id"` dall'input originale.

**Nota**  
Il `encoding/json` pacchetto può accedere solo ai campi esportati. Affinché siano esportati, i nomi dei campi nella struttura dell'evento devono avere l'iniziale maiuscola.

## Accesso e utilizzo dell'oggetto contestuale Lambda
<a name="golang-example-context"></a>

L'[oggetto contesto](golang-context.md): contiene informazioni sulla chiamata, sulla funzione e sull'ambiente di esecuzione. In questo esempio, abbiamo dichiarato questa variabile come `ctx` nella firma dell'handler:

```
func handleRequest(ctx context.Context, event json.RawMessage) error {
    ...
}
```

L'input `ctx context.Context` è un argomento facoltativo nell'handler della funzione. Per ulteriori informazioni sulle firme dell'handler accettate, consulta [Firme dell'handler valide per gli handler Go](#golang-handler-signatures).

Se si effettuano chiamate ad altri servizi utilizzando l'AWSSDK, l'oggetto context è necessario in alcune aree chiave. Ad esempio, per inizializzare correttamente i client SDK, è possibile caricare la configurazione AWS SDK corretta utilizzando l'oggetto di contesto come segue:

```
// Load AWS SDK configuration using the default credential provider chain
    cfg, err := config.LoadDefaultConfig(ctx)
```

Le stesse chiamate SDK possono richiedere l'oggetto context come input. Ad esempio, la `s3Client.PutObject` chiamata accetta l'oggetto context come primo argomento:

```
// Upload the receipt to S3
    _, err = s3Client.PutObject(ctx, &s3.PutObjectInput{
        ...
    })
```

Oltre alle richieste AWS SDK, puoi anche utilizzare l'oggetto context per il monitoraggio delle funzioni. Per ulteriori informazioni sulla copia di oggetti, consulta la sezione [Utilizzo dell'oggetto contestuale Lambda per recuperare le informazioni sulla funzione Go](golang-context.md).

## Firme dell'handler valide per gli handler Go
<a name="golang-handler-signatures"></a>

Durante la creazione di un gestore della funzione Lambda in Go sono disponibili diverse opzioni, ma è necessario attenersi alle seguenti regole:
+ Il gestore deve essere una funzione.
+ Il gestore può richiedere da 0 a 2 argomenti. Nel caso di due argomenti, il primo argomento deve implementare `context.Context`.
+ Il gestore può restituire da 0 a 2 argomenti. Nel caso di un singolo valore restituito, deve implementare `error`. Nel caso di due valori restituiti, il secondo valore deve implementare `error`.

Di seguito sono elencate le firme del gestore valide. `TIn` e `TOut` rappresentano le tipologie compatibili con la libreria standard *encoding/json*. Per ulteriori informazioni su come deserializzare queste tipologie, consultare [func Unmarshal](https://golang.org/pkg/encoding/json/#Unmarshal).
+ 

  ```
  func ()
  ```
+ 

  ```
  func () error
  ```
+ 

  ```
  func () (TOut, error)
  ```
+ 

  ```
  func (TIn) error
  ```
+ 

  ```
  func (TIn) (TOut, error)
  ```
+ 

  ```
  func (context.Context) error
  ```
+ 

  ```
  func (context.Context) (TOut, error)
  ```
+ 

  ```
  func (context.Context, TIn) error
  ```
+ 

  ```
  func (context.Context, TIn) (TOut, error)
  ```

## Utilizzo della AWS SDK per Go versione v2 nell'handler
<a name="golang-example-sdk-usage"></a>

Spesso, utilizzerai le funzioni Lambda per interagire o aggiornare altre AWS risorse. Il modo più semplice per interfacciarsi con queste risorse è usare la AWS SDK per Go v2.

**Nota**  
La AWS SDK per Go (v1) è in modalità manutenzione e terminerà il supporto il 31 luglio 2025. In futuro, si consiglia di utilizzare solo la AWS SDK per Go v2.

Per aggiungere dipendenze SDK alla tua funzione, usa il `go get` comando per i client SDK specifici di cui hai bisogno. Nel codice di esempio precedente, abbiamo usato la `config` libreria e la libreria. `s3` Aggiungi queste dipendenze eseguendo i seguenti comandi nella directory che contiene i file `go.mod` e `main.go `:

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

Quindi, importa le dipendenze di conseguenza nel blocco di importazione della tua funzione:

```
import (
    ...
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)
```

Quando utilizzi l'SDK nel tuo handler, configura i tuoi client con le impostazioni corrette. Il modo più semplice per farlo è utilizzare la catena di provider di [credenziali predefinita](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html#credentialProviderChain). Questo esempio illustra un modo per caricare questa configurazione:

```
// Load AWS SDK configuration using the default credential provider chain
    cfg, err := config.LoadDefaultConfig(ctx)
    if err != nil {
        log.Printf("Failed to load AWS SDK config: %v", err)
        return err
    }
```

Dopo aver caricato questa configurazione nella variabile `cfg`, è possibile passare la variabile nelle istanze del client. Il codice di esempio crea un'istanza di un client Amazon S3 come segue:

```
// Create an S3 client
    s3Client := s3.NewFromConfig(cfg)
```

In questo esempio, abbiamo inizializzato il nostro client Amazon S3 nella `init()` funzione per evitare di doverlo inizializzare ogni volta che richiamiamo la nostra funzione. Il problema è che nella `init()` funzione, Lambda non ha accesso all'oggetto context. Come soluzione alternativa, puoi inserire un segnaposto come `context.TODO()` durante la fase di inizializzazione. Successivamente, quando effettui una chiamata utilizzando il client, inserisci l'oggetto contestuale completo. Questa soluzione alternativa è descritta anche in[Utilizzo del contesto nelle inizializzazioni e nelle AWS chiamate dei client SDK](golang-context.md#golang-context-sdk).

Dopo aver configurato e inizializzato il client SDK, puoi utilizzarlo per interagire con altri servizi. AWS Il codice di esempio richiama l'`PutObject`API Amazon S3 nel modo seguente:

```
_, err = s3Client.PutObject(ctx, &s3.PutObjectInput{
    Bucket: &bucketName,
    Key:    &key,
    Body:   strings.NewReader(receiptContent),
})
```

## Accesso alle variabili d'ambiente
<a name="golang-example-envvars"></a>

Nel codice dell'handler, puoi fare riferimento a qualsiasi [variabile di ambiente](configuration-envvars.md) utilizzando il metodo `os.Getenv()`. In questo esempio, facciamo riferimento alla variabile di `RECEIPT_BUCKET` ambiente definita utilizzando la seguente riga di codice:

```
// Access environment variables
    bucketName := os.Getenv("RECEIPT_BUCKET")
    if bucketName == "" {
        log.Printf("RECEIPT_BUCKET environment variable is not set")
        return fmt.Errorf("missing required environment variable RECEIPT_BUCKET")
    }
```

## Utilizzo dello stato globale
<a name="golang-handler-state"></a>

Per evitare di creare nuove risorse ogni volta che richiami la funzione, puoi dichiarare e modificare le variabili globali all'esterno del codice dell'handler della funzione Lambda. Queste variabili globali vengono definite in un blocco o in un'`var`istruzione. Inoltre, l'handler può dichiarare una funzione `init()` che viene eseguita durante la fase di [inizializzazione](lambda-runtime-environment.md#runtimes-lifecycle-ib). Il metodo `init` si comporta allo stesso modo in AWS Lambda come nei programmi Go standard.

## Procedure consigliate di codice per le funzioni Go Lambda
<a name="go-best-practices"></a>

Segui le linee guida riportate nell'elenco seguente per utilizzare le best practice di codifica durante la creazione delle funzioni Lambda:
+ **Separare il gestore Lambda dalla logica principale.** In questo modo è possibile creare una funzione di cui è più semplice eseguire l'unit test.
+ **Ridurre la complessità delle dipendenze.** Preferire framework più semplici che si caricano velocemente all'avvio del [contesto di esecuzione](lambda-runtime-environment.md).
+ **Ridurre al minimo le dimensioni del pacchetto di implementazione al fine di soddisfare le esigenze di runtime.** In questo modo viene ridotta la quantità di tempo necessaria per il download del pacchetto e per la relativa decompressione prima dell'invocazione.

**Sfruttare il riutilizzo del contesto di esecuzione per migliorare le prestazioni della funzione.** Inizializzare i client SDK e le connessioni al database all'esterno del gestore di funzioni e memorizzare localmente nella cache gli asset statici nella directory `/tmp`. Le chiamate successive elaborate dalla stessa istanza della funzione possono riutilizzare queste risorse. Ciò consente di risparmiare sui costi riducendo i tempi di esecuzione delle funzioni.

Per evitare potenziali perdite di dati tra le chiamate, non utilizzare il contesto di esecuzione per archiviare dati utente, eventi o altre informazioni con implicazioni di sicurezza. Se la funzione si basa su uno stato mutabile che non può essere archiviato in memoria all'interno del gestore, considerare la possibilità di creare una funzione separata o versioni separate di una funzione per ogni utente.

**Utilizzare una direttiva keep-alive per mantenere le connessioni persistenti.** Lambda elimina le connessioni inattive nel tempo. Se si tenta di riutilizzare una connessione inattiva quando si richiama una funzione, si verificherà un errore di connessione. Per mantenere la connessione persistente, utilizzare la direttiva keep-alive associata al runtime. Per un esempio, vedere [Riutilizzo delle connessioni con Keep-Alive in Node.js](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html).

**Utilizzare [le variabili di ambiente](configuration-envvars.md) per passare i parametri operativi alla funzione.** Se ad esempio si scrive in un bucket Amazon S3 anziché impostare come hard-coded il nome del bucket in cui si esegue la scrittura, configurare tale nome come una variabile di ambiente.

**Evita di usare invocazioni ricorsive** nella tua funzione Lambda, in cui la funzione si richiama da sola o avvia un processo che potrebbe richiamare nuovamente la funzione. Ciò potrebbe provocare un volume non desiderato di invocazioni della funzione e un aumento dei costi. Se noti un volume indesiderato di invocazioni, imposta immediatamente la simultaneità riservata della funzione su `0` per interrompere tutte le invocazioni della funzione mentre si aggiorna il codice.

**Non utilizzare API non documentate e non pubbliche** nel codice della funzione Lambda. Per i tempi di esecuzione gestiti AWS Lambda, Lambda applica periodicamente aggiornamenti di sicurezza e funzionalità alle API interne di Lambda. Questi aggiornamenti API interni potrebbero essere incompatibili con le versioni precedenti, causando conseguenze indesiderate come errori di chiamata se la funzione ha una dipendenza su queste API non pubbliche. Consulta il [riferimento all'API](https://docs.aws.amazon.com/lambda/latest/api/welcome.html) per un elenco di API disponibili pubblicamente.

**Scrivi un codice idempotente.** La scrittura di un codice idempotente per le tue funzioni garantisce che gli eventi duplicati vengano gestiti allo stesso modo. Il tuo codice dovrebbe convalidare correttamente gli eventi e gestire con garbo gli eventi duplicati. Per ulteriori informazioni, consulta [Come posso rendere idempotente la mia funzione Lambda?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/).