Go и Serverless: как писать AWS Lambda функции, которым завидуют Python-разработчики

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему Go — это новый король Serverless (и точка)?

Когда речь заходит о serverless-архитектуре, в голову большинства разработчиков приходит JavaScript (Node.js) или Python. Это логично: они просты, популярны, и для них написаны тонны туториалов. Но есть одна проблема: холодный старт.

Представьте: вы запускаете Lambda-функцию на Python. Первый запрос после простоя обрабатывается 3-5 секунд. Пользователь ждет. Бизнес теряет деньги. Теперь представьте ту же функцию на Go: 100-200 миллисекунд. Чувствуете разницу?

Go (Golang) — это язык, созданный в недрах Google для решения задач, где важна производительность и простота. В мире serverless он дает три ключевых преимущества:

  • Мгновенный холодный старт — скомпилированный бинарник запускается за миллисекунды.
  • Низкое потребление памяти — вы платите меньше, а получаете больше.
  • Один бинарник — никаких зависимостей, просто загрузили и забыли.

В этой статье мы разберем, как писать serverless функции на Go для AWS Lambda, рассмотрим реальные примеры кода и сравним с альтернативами. Если вы устали ждать, пока "прогреется" Python-функция — добро пожаловать.

Как настроить AWS Lambda на Go: пошаговый гайд

Прежде чем писать код, давайте разберемся с инструментарием. Для работы с Go на AWS Lambda вам понадобятся:

  • Установленный Go (версия 1.21+).
  • Утилита aws-cli (или консоль AWS).
  • Базовое понимание, что такое Handler.

Шаг 1. Создаем проект

Создайте новую директорию и инициализируйте модуль:

mkdir go-lambda-example
cd go-lambda-example
go mod init example.com/lambda

Шаг 2. Пишем первую функцию

Создайте файл main.go. Вот минимальный пример serverless функции на Go, которая обрабатывает JSON и возвращает ответ:

package main

import (
    "context"
    "fmt"

    "github.com/aws/aws-lambda-go/lambda"
)

// MyEvent — структура входящего события
type MyEvent struct {
    Name string `json:"name"`
}

// MyResponse — структура ответа
type MyResponse struct {
    Message string `json:"message"`
    Status  int    `json:"status"`
}

// HandleRequest — главный обработчик Lambda
func HandleRequest(ctx context.Context, event MyEvent) (MyResponse, error) {
    if event.Name == "" {
        return MyResponse{Message: "Hello, anonymous!", Status: 200}, nil
    }
    return MyResponse{
        Message: fmt.Sprintf("Hello, %s! Welcome to serverless with Go.", event.Name),
        Status:  200,
    }, nil
}

func main() {
    lambda.Start(HandleRequest)
}

Важно: Функция должна принимать context.Context и возвращать (T, error). Это стандарт для Go Lambda.

Шаг 3. Компилируем для Linux

AWS Lambda работает на Linux, поэтому бинарник должен быть собран под эту ОС:

GOOS=linux GOARCH=amd64 go build -o bootstrap main.go

Обратите внимание: выходной файл должен называться bootstrap — это требование AWS Lambda для Go.

Шаг 4. Упаковываем и загружаем

Запакуйте бинарник в ZIP:

zip function.zip bootstrap

Теперь загрузите его в AWS Lambda через консоль или CLI. Готово! Ваша первая serverless функция на Go работает.

Продвинутый пример: работа с S3 и DynamoDB

Теперь, когда база освоена, давайте напишем что-то полезное. Допустим, нам нужно обрабатывать загрузку файлов в S3 и сохранять метаданные в DynamoDB. Это классический сценарий для serverless.

Установите необходимые SDK:

go get github.com/aws/aws-lambda-go/events
go get github.com/aws/aws-sdk-go-v2/service/s3
go get github.com/aws/aws-sdk-go-v2/service/dynamodb

Код обработчика:

package main

import (
    "context"
    "log"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

func handler(ctx context.Context, s3Event events.S3Event) error {
    // Загружаем конфиг AWS
    cfg, err := config.LoadDefaultConfig(ctx)
    if err != nil {
        log.Fatalf("Unable to load SDK config: %v", err)
    }

    // Создаем клиент DynamoDB
    client := dynamodb.NewFromConfig(cfg)

    for _, record := range s3Event.Records {
        // Извлекаем имя файла и бакета
        bucket := record.S3.Bucket.Name
        key := record.S3.Object.Key

        log.Printf("Processing file: %s from bucket: %s", key, bucket)

        // Сохраняем метаданные в DynamoDB
        _, err := client.PutItem(ctx, &dynamodb.PutItemInput{
            TableName: aws.String("FileMetadata"),
            Item: map[string]types.AttributeValue{
                "FileName": &types.AttributeValueMemberS{Value: key},
                "Bucket":   &types.AttributeValueMemberS{Value: bucket},
                "Size":     &types.AttributeValueMemberN{Value: "0"}, // упрощенно
            },
        })
        if err != nil {
            log.Printf("Error saving to DynamoDB: %v", err)
            return err
        }
    }

    return nil
}

func main() {
    lambda.Start(handler)
}

Этот код автоматически срабатывает при загрузке файла в S3 и записывает информацию в базу. Благодаря Go, функция запускается так быстро, что пользователь даже не заметит задержки.

Сравнение: Go vs Python для Serverless

Давайте будем честными. Python — отличный язык, но для serverless он не идеален. Вот таблица сравнения:

Характеристика Go Python
Холодный старт 100-300 мс 2-5 секунд (с зависимостями)
Размер пакета 5-15 МБ (один бинарник) 50+ МБ (с библиотеками)
Потребление памяти 10-30 МБ 50-150 МБ
Простота написания Сред

Блоги

Рекомендаций по книгам