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
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 Distribuzione delle funzioni Go Lambda con immagini di container
Argomenti
- Configurazione di Go Handler
- Esempio di codice della funzione Lambda
- Convenzioni di denominazione dei gestori
- Definizione e accesso all'oggetto evento di input
- Accesso e utilizzo dell'oggetto contestuale Lambda
- Firme dell'handler valide per gli handler Go
- Utilizzo della AWS SDK for Go versione v2 nell'handler
- Accesso alle variabili d'ambiente
- Utilizzo dello stato globale
- Procedure consigliate di codice per le funzioni Go Lambda
Configurazione di Go Handler
Una funzione Lambda scritta in Gogo 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/lambdago 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 filemain.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
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.
Esempio 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 funzionefunc main()
deve essere sempre denominatomain
. -
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.init()
-
func uploadReceiptToS3(...) {}
: questo è un metodo helper a cui fa riferimento il metodo dell'handler principalehandleRequest
. -
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 metodolambda.Start()
è il metodo principale dell'handler.
Affinché questa funzione funzioni correttamente, il suo ruolo di esecuzione 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
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, 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, per il file eseguibile è possibile usare qualsiasi nome.
Definizione e accesso all'oggetto evento di input
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 unOrder
:
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
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
L'oggetto contesto: 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.
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.
Firme dell'handler valide per gli handler Go
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 implementareerror
.
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
-
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 for Go versione v2 nell'handler
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 for Go v2.
Nota
La AWS SDK for Go (v1) è in modalità manutenzione e terminerà il supporto il 31 luglio 2025. In futuro, si consiglia di utilizzare solo la AWS SDK for 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. 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 inUtilizzo del contesto nelle inizializzazioni e nelle AWS chiamate dei client 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
Nel codice dell'handler, puoi fare riferimento a qualsiasi variabile di ambiente 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
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. 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
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.
-
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.
-
Utilizzare le variabili di ambiente 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 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?
.