Author your AWS Lambda functions in Go, effectively.
Author your AWS Lambda functions in Go, effectively.
THIS PROJECT IS DEPRECATED IN FAVOR OF ITS SUCCESSOR aws/aws-lambda-go
[][aws-home] [][eawsy-home]
Author your AWS Lambda functions in Go, effectively.
![Status][badge-status] ![License][badge-license] [![Help][badge-help]][eawsy-chat] [![Social][badge-social]][eawsy-twitter]
[AWS Lambda][aws-lambda-home] lets you run code without thinking about servers. [For now][aws-lambda-lng], you can author your AWS Lambda functions, natively, in [C#][aws-lambda-csharp], [Java][aws-lambda-java], [Node.js][aws-lambda-nodejs] and [Python][aws-lambda-python]. This project provides a native and full-featured shim for authoring your AWS Lambda functions in Go.
Table of Contents
generated with DocToc
package main
import "github.com/eawsy/aws-lambda-go-core/service/lambda/runtime"
func Handle(evt interface{}, ctx *runtime.Context) (string, error) {
return "Hello, World!", nil
}
wget -qO- https://github.com/eawsy/aws-lambda-go-shim/raw/master/src/preview.bash | bash
# "Hello, World!" executed in 0.45 ms
:hatching_chick: If you like the experience, please [spread the word][eawsy-spread]!
| Serialization | Context | Logging | Exceptions | [Environment][golang-env] | [Events][eawsy-evt] | [API Gateway][eawsy-net] |
|---|---|---|---|---|---|---|
| ![OK][ok] | ![OK][ok] | ![OK][ok] | ![OK][ok] | ![OK][ok] | ![OK][mok] | ![OK][ok] |
DISCLAIMER: We do not intend to compare Go with other languages but to appreciate the overhead of our shim compared to officially supported AWS Lambda languages.
:sunglasses: It is the 2nd fastest way to run an AWS Lambda function and makes the Node.js spawn process technique obsolete.
Requirements
docker pull eawsy/aws-lambda-go-shim:latest
go get -u -d github.com/eawsy/aws-lambda-go-core/...
wget -O Makefile https://git.io/vytH8
Code
package main
import (
"encoding/json"
"github.com/eawsy/aws-lambda-go-core/service/lambda/runtime"
)
func Handle(evt json.RawMessage, ctx *runtime.Context) (interface{}, error) {
// ...
}
Build
make
Deploy
You can use your preferred deployment method by providing it the following configuration:
For example, if you deploy your function through the AWS Lambda Management Console, you will have to fill a bunch of parameters like:
Considering for example the above preview section, we have the following structure:
.
└── preview
├── handler.go
└── Makefile
The handler.go file is where resides the main entrypoint of your AWS Lambda function. There is no restriction on how
many files and dependencies you can have, nor on how you must name your files and functions. Nevertheless however we
advocate to retain the handler name and to use Handle as the name of your entrypoint.
Let's review the content of handler.go:
1 package main
2
3 import "github.com/eawsy/aws-lambda-go-core/service/lambda/runtime"
4
5 func Handle(evt interface{}, ctx *runtime.Context) (string, error) {
6 return "Hello, World!", nil
7 }
For a seamless experience we leverage [Go 1.8 plugins][golang-plug] to separate the shim from your code. At run time, AWS Lambda loads our pre-compiled shim which in turn loads your code (your plugin). A plugin is a Go main package and that is why your entrypoint must be in the main package, as seen at line 1. Notice that this restriction only applies to your entrypoint and you are free to organize the rest of your code in different packages.
While your function is executing, it can interact with AWS Lambda to get useful runtime information such as, how much
time is remaining before AWS Lambda terminates your function, the AWS request id, etc. This information is passed as the
second parameter to your function via the runtime.Context object, as seen at line 5.
With [eawsy/aws-lambda-go-core][eawsy-ctx] we empower you with a full-featured context object to access any
available information in the exact same way that official AWS Lambda runtimes do. This is the only dependency you ever
need, as seen in line 3.
eawsy/aws-lambda-go-core dependency can be retrieved using the well known go get command:
go get -u -d github.com/eawsy/aws-lambda-go-core/...
[Go vendoring][golang-vnd] is also supported out of the box and behaves the same way expected when building usual go projects:
preview folder is inside GOPATH, then vendor folder prevails over GOPATH dependencies.preview folder is outside GOPATH, then vendor folder is ignored in favor of GOPATH dependencies.5 func Handle(evt interface{}, ctx *runtime.Context) (string, error) {
6 return "Hello, World!", nil
7 }
For AWS Lambda being able to call your handler, you have to [make it visible][golang-name] outside your plugin, as seen at line 5. There is no other naming restriction but keep in mind that if you change the name of your function, you must also update it in the AWS Lambda configuration.
Tip: Use a variable to expose a handler from the inside of a package:
var Handle = mypackage.MyHandle
For the rest, the handler follows the [AWS Lambda programming model][aws-lambda-model] by:
Taking 2 parameters:
json.RawMessage][golang-jsonraw] type, any other valid Go type or even your
own custom type. We also provide an [extensive set of predefined event definitions][eawsy-evt] if you plan to play
with [AWS Lambda event source mapping][aws-lambda-map].Returning 2 values:
interface{} type, any other valid Go type or even your own custom type to
leverage [fine grained json marshalling][golang-jsoncus].type CustomError struct {
s string
}
func (e *CustomError) Error() string {
return e.s
}
func Handle(evt interface{}, ctx *runtime.Context) (interface{}, error) {
return nil, &CustomError{"somthing bad happened"}
}
In line with the [AWS Lambda programming model][aws-lambda-model], one should be able to output logs using standard abilities of the language. Your function can contain logging statements using the official [Go log package][golang-log] and AWS Lambda writes theses logs to [AWS CloudWatch Logs][aws-cw-logs] asynchronously. There is no restriction on how to configure or use the Go log package.
package main
import (
"log"
"github.com/eawsy/aws-lambda-go-core/service/lambda/runtime"
)
func Handle(evt interface{}, ctx *runtime.Context) (interface{}, error) {
log.Println("Hello, World!")
return nil, nil
}
In the course of a normal and controlled execution flow, you can notify AWS Lambda an error occurred by returning an
error as explained above.
In case of unexpected situations when the ordinary flow of control stops and begins panicking and if you have not any
[recover mechanism][golang-recover] in place, then the stack trace is logged in AWS CloudWatch Logs and AWS Lambda is
notified an error occurred.
We provide a [Docker image][eawsy-docker] based on [Amazon Linux container image][aws-docker-image] to build your binary in the exact same environment than AWS Lambda. This image embeds our pre-compiled shim along with helper scripts to package your function. You can use it as such or [build your own custom image][docker-custom] from it:
docker pull eawsy/aws-lambda-go-shim:latest
Although not strictly required, we also provide an example Makefile to streamline common use cases. You are free to customize, modify and adapt it to your needs. Let's review its content briefly:
HANDLER ?= handler
PACKAGE ?= $(HANDLER)
docker:
@docker run ...
build:
@go build ...
pack:
@pack ...
Customize – The first two environment variables allow you to customize the name of your handler and the generated package:
make
.
└── preview
├── handler.go
├── handler.so
├── handler.zip
└── Makefile
HANDLER=myhandler PACKAGE=mypackage make
.
└── preview
├── handler.go
├── Makefile
├── myhandler.so
└── mypackage.zip
Dockerize – The docker target runs our Docker image and executes the rest of the build process inside it.
Build – The build target builds your code with the [plugin build mode][golang-mode]. Feel free to customize
build flags.
Package – The pack target is by far the most important one. It packages your previously built plugin and inject
our pre-compiled shim, with the correct name, into the package.
Be careful if you customize the example Makefile or if you build your own custom image, the way the shim is injected
into the package ensures its correct functioning.
The only intent of this project is to provide the most seamless and effective way to run Go on AWS Lambda. We do not provide any sugar and you are free to use your tools of predilection for deployment with the following settings in AWS Lambda:
python2.7handler.Handle (unless customized as explained above)Even if some of these behaviors can be overcome, we mimic the official AWS Lambda runtimes.
init function, it won't be written
in AWS CloudWatch Logs.[][eawsy-home]
This project is maintained and funded by Alsanium, SAS.
[We][eawsy-hom
No open issues yet, or sync has not completed.