

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Tentukan penangan fungsi Lambda di Go
<a name="golang-handler"></a>

*Handler* fungsi Lambda Anda adalah metode dalam kode fungsi Anda yang memproses peristiwa. Saat fungsi Anda diaktifkan, Lambda menjalankan metode handler. Fungsi Anda berjalan sampai handler mengembalikan respons, keluar, atau batas waktu.

Halaman ini menjelaskan cara bekerja dengan penangan fungsi Lambda di Go, termasuk penyiapan proyek, konvensi penamaan, dan praktik terbaik. Halaman ini juga menyertakan contoh fungsi Go Lambda yang mengambil informasi tentang pesanan, menghasilkan tanda terima file teks, dan menempatkan file ini dalam bucket Amazon Simple Storage Service (Amazon S3). Untuk informasi tentang cara menerapkan fungsi Anda setelah menulisnya, lihat [Deploy fungsi Go Lambda dengan arsip file .zip](golang-package.md) atau[Deploy fungsi Lambda Go dengan gambar kontainer](go-image.md).

**Topics**
+ [Menyiapkan proyek Handler Go Anda](#golang-handler-setup)
+ [Contoh kode fungsi Go Lambda](#golang-example-code)
+ [Konvensi penamaan handler](#golang-handler-naming)
+ [Mendefinisikan dan mengakses objek peristiwa input](#golang-example-input)
+ [Mengakses dan menggunakan objek konteks Lambda](#golang-example-context)
+ [Tanda tangan handler yang valid untuk penangan Go](#golang-handler-signatures)
+ [Menggunakan AWS SDK untuk Go v2 di handler Anda](#golang-example-sdk-usage)
+ [Mengakses variabel lingkungan](#golang-example-envvars)
+ [Menggunakan status global](#golang-handler-state)
+ [Praktik terbaik kode untuk fungsi Go Lambda](#go-best-practices)

## Menyiapkan proyek Handler Go Anda
<a name="golang-handler-setup"></a>

Fungsi Lambda yang ditulis di [Go](https://golang.org/) diprogram sebagai Go executable. Anda dapat menginisialisasi proyek fungsi Go Lambda dengan cara yang sama Anda menginisialisasi proyek Go lainnya menggunakan perintah berikut: `go mod init`

```
go mod init {{example-go}}
```

Di sini, `example-go` adalah nama modul. Anda dapat mengganti ini dengan apa saja. Perintah ini menginisialisasi proyek Anda dan menghasilkan `go.mod` file yang mencantumkan dependensi proyek Anda.

Gunakan `go get` perintah untuk menambahkan dependensi eksternal ke proyek Anda. Misalnya, untuk semua fungsi Lambda di Go, Anda harus menyertakan [ github. com/awsgo/lambda](https://github.com/aws/aws-lambda-go/tree/master/lambda)paket /aws-lambda-, yang mengimplementasikan model pemrograman Lambda untuk Go. Sertakan paket ini dengan `go get` perintah berikut:

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

Kode fungsi Anda harus berada dalam file Go. Dalam contoh berikut, kami menamai file ini`main.go`. Dalam file ini, Anda mengimplementasikan logika fungsi inti Anda dalam metode handler, serta `main()` fungsi yang memanggil handler ini.

## Contoh kode fungsi Go Lambda
<a name="golang-example-code"></a>

Contoh kode fungsi Go Lambda berikut mengambil informasi tentang pesanan, menghasilkan tanda terima file teks, dan menempatkan file ini dalam bucket Amazon S3.

**Example `Fungsi main.go Lambda`**  

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

`main.go`File ini berisi bagian kode berikut:
+ `package main`: Di Go, paket yang berisi `func main()` fungsi Anda harus selalu diberi nama`main`.
+ `import`blok: Gunakan blok ini untuk menyertakan pustaka yang dibutuhkan fungsi Lambda Anda.
+ `type Order struct {}`blok: Tentukan bentuk peristiwa input yang diharapkan dalam struct Go ini.
+ `var ()`blok: Gunakan blok ini untuk menentukan variabel global apa pun yang akan Anda gunakan dalam fungsi Lambda Anda.
+ `func init() {}`: Sertakan kode apa pun yang Anda ingin Lambda jalankan selama fase in [ isialisasi ](lambda-runtime-environment.md#runtimes-lifecycle-ib) dalam metode ini`init()`.
+ `func uploadReceiptToS3(...) {}`: Ini adalah metode pembantu yang direferensikan oleh metode `handleRequest` handler utama.
+ `func handleRequest(ctx context.Context, event json.RawMessage) error {}`: Ini adalah metode handler ** utama**, yang berisi logika aplikasi utama Anda.
+ `func main() {}`: Ini adalah titik masuk yang diperlukan untuk handler Lambda Anda. Argumen untuk `lambda.Start()` metode ini adalah metode handler utama Anda.

Agar fungsi ini berfungsi dengan baik, peran [ pelaksanaannya ](lambda-intro-execution-role.md) harus memungkinkan `s3:PutObject` tindakan. Juga, pastikan Anda mendefinisikan variabel `RECEIPT_BUCKET` lingkungan. Setelah pemanggilan berhasil, bucket Amazon S3 harus berisi file tanda terima.

## Konvensi penamaan handler
<a name="golang-handler-naming"></a>

Untuk fungsi Lambda di Go, Anda dapat menggunakan nama apa pun untuk handler. Dalam contoh ini, nama metode handler adalah`handleRequest`. Untuk mereferensikan nilai handler dalam kode Anda, Anda dapat menggunakan variabel `_HANDLER` lingkungan.

Untuk fungsi Go yang digunakan menggunakan paket pener [ apan.zip](golang-package.md), file yang dapat dieksekusi yang berisi kode fungsi Anda harus diberi `bootstrap` nama. Selain itu, `bootstrap` file harus berada di root file.zip. Untuk fungsi Go yang digunakan menggunakan gambar kon [ tainer](go-image.md#go-image-provided), Anda dapat menggunakan nama apa pun untuk file yang dapat dieksekusi.

## Mendefinisikan dan mengakses objek peristiwa input
<a name="golang-example-input"></a>

JSON adalah format input yang paling umum dan standar untuk fungsi Lambda. Dalam contoh ini, fungsi mengharapkan input yang mirip dengan berikut ini:

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

Saat bekerja dengan fungsi Lambda di Go, Anda dapat menentukan bentuk peristiwa input yang diharapkan sebagai struct Go. Dalam contoh ini, kita mendefinisikan struct untuk mewakili: `Order`

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

Struct ini cocok dengan bentuk input yang diharapkan. Setelah Anda menentukan struct Anda, Anda dapat menulis tanda tangan handler yang mengambil tipe JSON generik yang kompatibel dengan pustaka [ encoding/json ](https://pkg.go.dev/encoding/json) standar. Anda kemudian dapat mendeserialisasikannya ke struct Anda menggunakan fungsi [ func Unmarshal. ](https://golang.org/pkg/encoding/json/#Unmarshal) Ini diilustrasikan dalam beberapa baris pertama 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
    ...
}
```

Setelah deserialisasi ini, Anda dapat mengakses bidang variabel. `order` Misalnya, `order.OrderID` mengambil nilai `"order_id"` dari input asli.

**catatan**  
`encoding/json`Paket hanya dapat mengakses bidang yang diekspor. Untuk diekspor, nama bidang dalam struktur peristiwa harus dalam huruf kapital.

## Mengakses dan menggunakan objek konteks Lambda
<a name="golang-example-context"></a>

Objek [ konteks Lambda ](golang-context.md) berisi informasi tentang pemanggilan, fungsi, dan lingkungan eksekusi. Dalam contoh ini, kita mendeklarasikan variabel ini seperti `ctx` pada tanda tangan handler:

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

In `ctx context.Context` put adalah argumen opsional dalam handler fungsi Anda. Untuk informasi selengkapnya tentang tanda tangan handler yang diterima, lihat[Tanda tangan handler yang valid untuk penangan Go](#golang-handler-signatures).

Jika Anda melakukan panggilan ke layanan lain menggunakan AWS SDK, objek konteks diperlukan di beberapa area utama. Misalnya, untuk menginisialisasi klien SDK dengan benar, Anda dapat memuat konfigurasi AWS SDK yang benar menggunakan objek konteks sebagai berikut:

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

Panggilan SDK sendiri mungkin memerlukan objek konteks sebagai input. Misalnya, `s3Client.PutObject` panggilan menerima objek konteks sebagai argumen pertamanya:

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

Di luar permintaan AWS SDK, Anda juga dapat menggunakan objek konteks untuk pemantauan fungsi. Untuk informasi selengkapnya tentang objek konteks, lihat[Menggunakan objek konteks Lambda untuk mengambil informasi fungsi Go](golang-context.md).

## Tanda tangan handler yang valid untuk penangan Go
<a name="golang-handler-signatures"></a>

Anda memiliki beberapa pilihan ketika membangun handler fungsi Lambda di Go, tetapi Anda harus mematuhi aturan berikut:
+ Handler harus berupa fungsi.
+ Handler dapat mengambil antara 0 dan 2 argumen. Jika ada dua argumen, argumen pertama harus menerapkan `context.Context`.
+ Handler dapat mengembalikan antara 0 dan 2 argumen. Jika ada nilai kembali tunggal, nilai harus menerapkan `error`. Jika ada dua nilai kembali, nilai kedua harus menerapkan `error`.

Berikut ini mencantumkan tanda tangan handler yang valid. `TIn`dan `TOut` mewakili tipe yang kompatibel dengan perpustakaan * encoding/json * standar. Untuk informasi selengkapnya, lihat [func Unmarshal](https://golang.org/pkg/encoding/json/#Unmarshal) untuk mempelajari cara tipe-tipe ini dideserialisasikan.
+ 

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

## Menggunakan AWS SDK untuk Go v2 di handler Anda
<a name="golang-example-sdk-usage"></a>

Seringkali, Anda akan menggunakan fungsi Lambda untuk berinteraksi dengan atau membuat pembaruan ke AWS sumber daya lain. Cara paling sederhana untuk berinteraksi dengan sumber daya ini adalah dengan menggunakan [AWS SDK untuk Go v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2).

**catatan**  
 AWS SDK untuk Go (v1) dalam mode pemeliharaan, dan akan mencapai akhir dukungan pada 31 Juli 2025. Kami menyarankan Anda hanya menggunakan AWS SDK untuk Go v2 ke depan.

Untuk menambahkan dependensi SDK ke fungsi Anda, gunakan `go get` perintah untuk klien SDK tertentu yang Anda butuhkan. Dalam contoh kode sebelumnya, kita menggunakan per `config` pustakaan dan per `s3` pustakaan. Tambahkan dependensi ini dengan menjalankan perintah berikut di direktori yang berisi `main.go ` file `go.mod` dan Anda:

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

Kemudian, impor dependensi yang sesuai di blok impor fungsi Anda:

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

Saat menggunakan SDK di handler Anda, konfigurasikan klien Anda dengan pengaturan yang tepat. Cara paling sederhana untuk melakukan ini adalah dengan menggunakan rantai [ penyedia kredensia ](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html#credentialProviderChain) default. Contoh ini menggambarkan satu cara untuk memuat konfigurasi ini:

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

Setelah memuat konfigurasi ini ke dalam `cfg` variabel, Anda dapat meneruskan variabel ini ke instansiasi klien. Kode contoh membuat klien Amazon S3 sebagai berikut:

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

Dalam contoh ini, kami menginisialisasi klien Amazon S3 kami dalam `init()` fungsi untuk menghindari keharusan menginisialisasi setiap kali kami memanggil fungsi kami. Masalahnya adalah bahwa dalam `init()` fungsi, Lambda tidak memiliki akses ke objek konteks. Sebagai solusinya, Anda dapat memasukkan placeholder seperti `context.TODO()` selama fase inisialisasi. Kemudian, ketika Anda melakukan panggilan menggunakan klien, berikan objek konteks penuh. Solusi ini juga dijelaskan di. [Menggunakan konteks di AWS Inisialisasi dan panggilan klien SDK](golang-context.md#golang-context-sdk)

Setelah mengonfigurasi dan menginisialisasi klien SDK, Anda kemudian dapat menggunakannya untuk berinteraksi dengan AWS layanan lain. Kode contoh memanggil `PutObject` API Amazon S3 sebagai berikut:

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

## Mengakses variabel lingkungan
<a name="golang-example-envvars"></a>

Dalam kode handler Anda, Anda dapat mereferensikan variabel [ lingkungan apa pun ](configuration-envvars.md) dengan menggunakan `os.Getenv()` metode ini. Dalam contoh ini, kita mereferensi `RECEIPT_BUCKET` kan variabel lingkungan yang ditentukan menggunakan baris kode berikut:

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

## Menggunakan status global
<a name="golang-handler-state"></a>

Untuk menghindari pembuatan sumber daya baru setiap kali Anda memanggil fungsi Anda, Anda dapat mendeklarasikan dan memodifikasi variabel global di luar kode handler fungsi Lambda Anda. Anda mendefinisikan variabel global ini dalam `var` blok atau pernyataan. Selain itu, handler Anda dapat mendeklarasikan `init()` fungsi yang dijalankan selama fase [ in ](lambda-runtime-environment.md#runtimes-lifecycle-ib) isialisasi. `init`Metode ini berperilaku sama AWS Lambda seperti dalam program Go standar.

## Praktik terbaik kode untuk fungsi Go Lambda
<a name="go-best-practices"></a>

Patuhi pedoman dalam daftar berikut untuk menggunakan praktik pengkodean terbaik saat membangun fungsi Lambda Anda:
+ **Pisahkan handler Lambda dari logika inti Anda. ** Dengan pendekatan ini, Anda dapat membuat fungsi yang lebih dapat diuji unit.
+ **Minimalkan kompleksitas dependensi Anda. ** Utamakan memilih kerangka kerja lebih sederhana yang cepat dimuat dalam memulai [lingkungan eksekusi](lambda-runtime-environment.md).
+ **Minimalkan ukuran paket penerapan Anda sesuai kebutuhan runtime. ** Ini mengurangi jumlah waktu yang diperlukan untuk paket penerapan Anda untuk diunduh dan dibongkar sebelum pemanggilan.

**Manfaatkan penggunaan kembali lingkungan eksekusi untuk meningkatkan kinerja fungsi Anda. ** Inisialisasi klien SDK dan koneksi basis data di luar fungsi handler, dan lakukan caching aset statis secara lokal di direktori `/tmp`. Invokasi selanjutnya yang diproses oleh instans yang sama dari fungsi Anda dapat menggunakan kembali sumber daya ini. Ini menghemat biaya dengan mengurangi waktu pengoperasian fungsi.

Untuk menghindari potensi kebocoran data di seluruh invokasi, jangan menggunakan lingkungan eksekusi untuk menyimpan data pengguna, peristiwa, atau informasi lainnya implikasi keamanan. Jika fungsi Anda bergantung pada status yang dapat disenyapkan yang tidak dapat disimpan dalam memori di dalam handler, pertimbangkan untuk membuat fungsi terpisah atau versi terpisah dari fungsi untuk setiap pengguna.

**Gunakan direktif keep-alive untuk mempertahankan koneksi yang persisten. ** Lambda membersihkan koneksi idle dari waktu ke waktu. Mencoba menggunakan ulang koneksi idle saat mengidentifikasi suatu fungsi akan menyebabkan kesalahan koneksi. Untuk mempertahankan koneksi yang persisten, gunakan arahan tetap aktif yang berkaitan dengan runtime Anda. Sebagai contoh, lihat Menggunakan Kem [ bali Koneksi dengan Keep-Alive in Node.js](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html).

**Gunakan variabel [ lingkungan ](configuration-envvars.md) untuk meneruskan parameter operasional ke fungsi Anda. ** Misalnya, jika Anda ingin menulis ke bucket Amazon S3 alih-alih melakukan hard-coding nama bucket yang Anda tulis, konfigurasikan nama bucket sebagai variabel lingkungan.

**Hindari menggunakan pemanggilan rekursif ** dalam fungsi Lambda Anda, di mana fungsi memanggil dirinya sendiri atau memulai proses yang dapat memanggil fungsi lagi. Hal ini dapat menyebabkan volume invokasi fungsi yang tidak diinginkan dan peningkatan biaya. Jika Anda melihat volume pemanggilan yang tidak diinginkan, setel fungsi reservasi konkurensi ke `0` segera untuk membatasi semua pemanggilan ke fungsi, saat Anda memperbarui kode.

**Jangan gunakan API non-publik yang tidak terdokumentasi ** dalam kode fungsi Lambda Anda. Untuk runtime AWS Lambda terkelola, Lambda secara berkala menerapkan pembaruan keamanan dan fungsional ke API internal Lambda. Pembaruan API internal ini mungkin tidak kompatibel ke belakang, yang menyebabkan konsekuensi yang tidak diinginkan seperti kegagalan pemanggilan jika fungsi Anda memiliki ketergantungan pada API non-publik ini. Lihat [ referensi API ](https://docs.aws.amazon.com/lambda/latest/api/welcome.html) untuk daftar API yang tersedia untuk umum.

**Tulis kode idempotent. ** Menulis kode idempotent untuk fungsi Anda memastikan bahwa peristiwa duplikat ditangani dengan cara yang sama. Kode Anda harus memvalidasi peristiwa dengan benar dan menangani peristiwa duplikat dengan anggun. Untuk informasi lebih lanjut, lihat [ Bagaimana cara membuat fungsi Lambda saya idempoten? ](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/).