cd src/url_service/terraform
terraform init -backend-config="env/local-dev/env.tfbackend" -reconfigure
terraform plan -var-file="env/local-dev/env.tfvars"
terraform apply -var-file="env/local-dev/env.tfvars"# Create a new folder under src/url_service/, e.g., create_short_url
mkdir ./src/url_service/create_short_url
# cd src/url_service/<function_name>
cd ./src/url_service/create_short_url
# initialize go module github.com/aws-educate-tw/url-shortener/src/<service>/<function_name>
go mod init github.com/aws-educate-tw/url-shortener/src/url_service/create_short_url
# add aws-lambda-go dependency
go get github.com/aws/aws-lambda-go/lambda
# tidy up dependencies
go mod tidy
# Create directory structure for Hexagonal Architecture
mkdir -p cmd internal/config internal/domain internal/service internal/adapters/handler internal/adapters/repository
# create main.go in the correct location
touch cmd/main.go
# create Dockerfile
touch DockerfileWe follow the Hexagonal Architecture (Ports and Adapters) for our Lambda functions to ensure testability and separation of concerns.
src/url_service/<function_name>/
├── cmd/
│ └── main.go # Entry point (Wiring everything together)
├── internal/
│ ├── config/ # Configuration loading (Env vars)
│ │ └── config.go
│ ├── domain/ # Pure business logic & Interfaces
│ │ ├── model.go # Entities (e.g., ShortURL)
│ │ └── repository.go # Interfaces (Output Ports)
│ ├── service/ # Application Logic (Use Cases)
│ │ └── service.go # Business flow implementation
│ └── adapters/ # Infrastructure implementations
│ ├── handler/ # Lambda Handler (Primary Adapter)
│ │ └── lambda.go
│ └── repository/ # Database Implementation (Secondary Adapter)
│ └── dynamodb.go
├── go.mod
├── go.sum
└── Dockerfile
- cmd/main.go: The Composition Root. It loads config, initializes adapters, injects dependencies into the service, and starts the Lambda handler.
- internal/domain: Contains pure business entities and interfaces (Ports). It has NO external dependencies (no AWS SDK, no HTTP).
- internal/service: Implements the business use cases. It depends only on the Domain layer.
- internal/adapters: Contains the implementation of interfaces (e.g., DynamoDB repository) and the entry point handler (Lambda).
- internal/config: Handles loading configuration from environment variables.