

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 waktu habis.

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 di 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 Go handler Anda](#golang-handler-setup)
+ [Contoh kode fungsi Go Lambda](#golang-example-code)
+ [Konvensi penamaan handler](#golang-handler-naming)
+ [Mendefinisikan dan mengakses objek peristiwa masukan](#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 Go handler 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 menggantinya 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/aws/aws-lambda-go/lambda](https://github.com/aws/aws-lambda-go/tree/master/lambda)paket, 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 hidup dalam file Go. Dalam contoh berikut, kami memberi nama file ini`main.go`. Dalam file ini, Anda menerapkan 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 di bucket Amazon S3.

**Example `main.go`Fungsi 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`block: Gunakan blok ini untuk menyertakan pustaka yang dibutuhkan fungsi Lambda Anda.
+ `type Order struct {}`block: Tentukan bentuk peristiwa input yang diharapkan dalam struct Go ini.
+ `var ()`block: 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 inisialisasi](lambda-runtime-environment.md#runtimes-lifecycle-ib) dalam metode ini. `init()`
+ `func uploadReceiptToS3(...) {}`: Ini adalah metode helper 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 penangan 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 bahwa 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.zip deployment](golang-package.md), file yang dapat dieksekusi yang berisi kode fungsi Anda harus diberi nama. `bootstrap` Selain itu, `bootstrap` file harus berada di root file.zip. Untuk fungsi Go yang digunakan menggunakan [gambar kontainer](go-image.md#go-image-provided), Anda dapat menggunakan nama apa pun untuk file yang dapat dieksekusi.

## Mendefinisikan dan mengakses objek peristiwa masukan
<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 yang berikut:

```
{
    "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 menggunakan tipe JSON generik yang kompatibel dengan pustaka standar encoding/json.](https://pkg.go.dev/encoding/json) Anda kemudian dapat deserialisasinya ke dalam struct Anda menggunakan [fungsi func](https://golang.org/pkg/encoding/json/#Unmarshal) 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 dari `"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](golang-context.md) Lambda berisi informasi tentang lingkungan pemanggilan, fungsi, dan eksekusi. Dalam contoh ini, kami mendeklarasikan variabel ini seperti `ctx` pada tanda tangan handler:

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

`ctx context.Context`Input 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 lebih lanjut 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`.

Daftar berikut ini mencantumkan tanda tangan handler yang valid. `TIn` dan `TOut` mewakili tipe yang kompatibel dengan pustaka standar *encoding/json*. 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 sumber daya lain AWS . Cara termudah 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 end-of-support 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 `config` perpustakaan dan `s3` perpustakaan. Tambahkan dependensi ini dengan menjalankan perintah berikut di direktori yang berisi file Anda `go.mod` dan`main.go `:

```
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 termudah untuk melakukannya adalah dengan menggunakan [rantai penyedia kredensyal default](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html#credentialProviderChain). Contoh ini menggambarkan salah 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 instantiasi klien. Kode contoh membuat instance klien Amazon S3 sebagai berikut:

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

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

Setelah Anda mengkonfigurasi dan menginisialisasi klien SDK Anda, Anda kemudian dapat menggunakannya untuk berinteraksi dengan layanan lain AWS . Kode contoh memanggil Amazon S3 `PutObject` API 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](configuration-envvars.md) apa pun dengan menggunakan `os.Getenv()` metode ini. Dalam contoh ini, kami mereferensikan variabel `RECEIPT_BUCKET` 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 menjalankan fungsi, Anda dapat mendeklarasikan dan memodifikasi variabel global di luar kode penangan 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 inisialisasi.](lambda-runtime-environment.md#runtimes-lifecycle-ib) `init`Metode ini berperilaku sama AWS Lambda seperti pada 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.** Ini memungkinkan Anda untuk membuat fungsi yang lebih dapat teruji.
+ **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-nya.** Ini akan mengurangi jumlah waktu yang dibutuhkan untuk mengunduh dan membongkar paket deployment Anda sebelum invokasi.

**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 arahan 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 Kembali Koneksi dengan Keep-Alive di 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 konkurensi fungsi cadangan untuk `0` segera membatasi semua pemanggilan ke fungsi, saat Anda memperbarui kode.

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

**Tulis kode idempoten.** Menulis kode idempoten 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 selengkapnya, lihat [Bagaimana cara membuat fungsi Lambda saya idempoten?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/) .