Create a main.go
file:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
func main() {
runtime_api := os.Getenv("AWS_LAMBDA_RUNTIME_API")
base_url := "http://" + runtime_api + "/2018-06-01/runtime/invocation/"
for {
resp, err := http.Get(base_url + "next")
if err != nil {
log.Fatalf("Failed to get next invocation: %v", err)
}
requestID := resp.Header.Get("Lambda-Runtime-Aws-Request-Id")
var event map[string]interface{}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Failed ioutil.ReadAll: %v", err)
}
err = json.Unmarshal(body, &event)
if err != nil {
log.Fatalf("Failed json.Unmarshal: %v", err)
}
resp.Body.Close()
response, err := handler(event)
if err != nil {
log.Fatalf("Failed json.Marshal: %v", err)
}
responseURL := base_url + requestID + "/response"
_, err = http.Post(responseURL, "application/json", response)
if err != nil {
log.Fatalf("Failed to post response: %v", err)
}
}
}
func handler(event map[string]interface{}) (*bytes.Buffer, error) {
response := map[string]interface{}{
"message": fmt.Sprintf("Hello %s!", event["name"]),
}
responseBody, err := json.Marshal(response)
if err != nil {
return nil, err
}
return bytes.NewBuffer(responseBody), nil
}
Compile it to bootstrap
binary as expected by AWS Lambda:
docker run --rm -ti -w /home -v "${PWD}":/home \
-e GOOS=linux -e GOARCH=arm64 -e CGO_ENABLED=0 \
golang:1.22 go build -o bootstrap main.go
Now zip it as AWS requires:
zip lambda.zip bootstrap
Use the following commands from AWS Cloud Shell or from local terminal assuming you have an active AWS session:
export FUNC_NAME=andrei-test
export ROLE_NAME="${FUNC_NAME}-role"
export ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
aws iam create-role --role-name "${ROLE_NAME}" --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}' | jq
aws iam attach-role-policy \
--role-name "${ROLE_NAME}" \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws lambda create-function \
--function-name "${FUNC_NAME}" \
--role "arn:aws:iam::${ACCOUNT_ID}:role/${ROLE_NAME}" \
--runtime provided.al2023 \
--architectures arm64 \
--handler whatever \
--zip-file fileb://lambda.zip | jq
Now test invoking your function
aws lambda invoke \
--function-name "${FUNC_NAME}" \
--cli-binary-format raw-in-base64-out \
--payload '{"name":"test"}' \
_.json | jq && cat _.json | jq && rm _.json
Should see the output
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
{
"message": "Hello test!"
}
When you need to update your function:
aws lambda update-function-code \
--function-name "${FUNC_NAME}" \
--zip-file fileb://lambda.zip | jq
After you done with testing, don't forget to remove the function, the role and an auto-created log group:
aws lambda delete-function --function-name "${FUNC_NAME}"
# detach all role policies
for ARN in $(aws iam list-attached-role-policies --role-name "${ROLE_NAME}" \
--query 'AttachedPolicies[].PolicyArn' --output text); do
aws iam detach-role-policy --role-name "${ROLE_NAME}" --policy-arn "${ARN}"; done
aws iam delete-role --role-name "${ROLE_NAME}"
aws logs delete-log-group --log-group-name "/aws/lambda/${FUNC_NAME}"
Here is example of
main.go
usingaws-lambda-go
package:Run inside the container:
go mod init example/mymodule go get github.com/aws/aws-lambda-go/lambda go mod download && go mod verify
and then build as in the original example.