- Print
- PDF
Go
- Print
- PDF
Available in Classic and VPC
This document describes how to create and use actions of Go (as a language) format in a variety of ways, and application examples.
Create actions
A Go code can have one or more Go source files. The entry point of an action made with Go sources is a function in the main package. The main function's default name is Main, but can be modified to a different name depending on the user's choice. However, the name always starts with an uppercase English letter. The main function needs to be created in the format detailed in the following description:
func Main(event map[string]interface{}) map[string]interface{}
A code written in Go may contain multiple functions, but the main
function must be declared as the starting point of a program. With this taken into account, the following is the simple example code hello
in Go, printing "Hello World" along with a name and location:
package main
import "log"
func Main(obj map[string]interface{}) map[string]interface{} {
name, ok := obj["name"].(string)
if !ok {
name = "world"
}
msg := make(map[string]interface{})
msg["message"] = "Hello, " + name + "!"
log.Printf("name=%s\n", name)
return msg
}
The following is the process of an action called "hello" in the console, using the code written above:
Supported formats
The following are formats that can be supported in the execution environment:
- Executable binary of a Linux ELF execution file compiled for AMD64 architecture
- ZIP file that contains ELF execution file compiled for AMD64 architecture, and execution file in the
exec
name at the top level - Single source file compiled in Go
- ZIP files that don't contain execution binary files on the top level (folder) are compiled and executed later.
The correct form of binaries can be cross-compiled on all platforms that support Go with GOOS=Linux
and GOARCH=amd64
. It's safer to use the advance compile feature and use the same compiler as in the execution environment.
Create actions by using Go Modules
For using external libraries in the go1.19 version, use Go Modules
. When you're not using Go Modules
, the source code must be directly included.
Next is the stepwise guide on how to import the following package in actions using go mod
: The relevant method requires the Internet communication and in a VPC environment, the NAT G/W settings are required. For more information about NAT G/W, see NAT Gateway Guide.
import "github.com/rs/zerolog"
- Reset new modules
Reset a new module by executing the following command: If you execute the command, a go.mod
file will be created.
go mod init <module>
- Create
main.go
See the following example code to create main.go
:
package main
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func init() {
zerolog.TimeFieldFormat = ""
}
func Main(obj map[string]interface{}) map[string]interface{} {
name, ok := obj["name"].(string)
if !ok {
name = "world"
}
log.Debug().Str("name", name).Msg("Hello")
msg := make(map[string]interface{})
msg["module-main"] = "Hello, " + name + "!"
return msg
}
- Import dependency
Update go.mod
file by executing the following command, and create go.sum
file:
go get github.com/rs/zerolog@v1.19.0
- Package and upload actions
Compress the package by executing the following command and upload it to create actions:
zip -r action.zip go.mod go.sum main.go
Use package and vendor
to create actions
When writing codes, you may need to package dependency files along with one action file. In such cases, related files can be compressed in a file, packaged, and an action can be created using the compressed file.
The following are the three types available for creating actions using ZIP files:
- When all features are implemented in a
main
package - When some packages are separated and built other than the
main
package - When it is implemented in the form that includes parts that are dependent on third parties for feature implementation
If all features are in a default package, you can place all the source files in the top level of the ZIP file.
Use package folder
If some features belong to a different package than a part where the main function is executed, the folder needs to be packaged under a package name in the format such as hello/
. The following is a packaging example:
golang-main-package/
- src/
- main.go
- hello/
- hello.go
- hello_test.go
To run tests and edit without errors, the src
folder needs to be used. The default package's content is placed under src/
, and the source codes of the hello
package are placed in the hello/
folder. However, the sub-package must be imported like import "hello"
to use it. This means that a parent directory of src
must be set up in the user's GOPATH
if compiled in a local development environment. If the user uses an editor such a VSCode, the go.inferGopath
option needs to be enabled.
When sending the source, compress the src
folder's content, rather than the top directory as follows:
cd src
zip -r ../hello.zip *
cd ..
The following is the example code for the above:
src/main.go
package main
import (
"fmt"
"hello"
)
// Main forwading to Hello
func Main(args map[string]interface{}) map[string]interface{} {
fmt.Println("Main")
return hello.Hello(args)
}
src/hello/hello.go
package hello
import (
"fmt"
)
// Hello receive an event in format
// { "name": "Mike"}
// and returns a greeting in format
// { "greetings": "Hello, Mike"}
func Hello(args map[string]interface{}) map[string]interface{} {
res := make(map[string]interface{})
greetings := "world"
name, ok := args["name"].(string)
if ok {
greetings = name
}
res["golang-main-package"] = "Hello, " + greetings
fmt.Printf("Hello, %s\n", greetings)
return res
}
src/hello/hello_test.go
package hello
import (
"encoding/json"
"fmt"
)
func ExampleHello() {
var input = make(map[string]interface{})
input["name"] = "Mike"
output := Hello(input)
json, _ := json.Marshal(output)
fmt.Printf("%s", json)
// Output:
// Hello, Mike
// {"golang-main-package":"Hello, Mike"}
}
func ExampleHello_noName() {
var input = make(map[string]interface{})
output := Hello(input)
json, _ := json.Marshal(output)
fmt.Printf("%s", json)
// Output:
// Hello, world
// {"golang-main-package":"Hello, world"}
}
Use the vendor
folder
If a different third party library needs to be used, you don't download the runtime library via the Internet when compiling, but should use the vendor
folder structure to download and place. This page provides instructions on how to use the dep
tool.
The vendor
folder must include the src
folder, package folder, and vendor
folder. It won't work on the top level folder. If you want to use files contained in the main
package, it needs to be placed in the subfolder specified as main
, rather than the top level folder. For example, let's suppose a circumstance where a package needs to be imported for the file src/hello/hello.go
as follows:
import "github.com/sirupsen/logrus"
In such a case, proceed as follows to create the vendor
folder.
Install the dep tool.
Go to the
src/hello
folder.cd ./src/hello
- Note that it's not the
src
folder, butsrc/hello
.
- Note that it's not the
Run
DEPPROJECTROOT=$(realpath $PWD/../..) dep init
.- This tool searches and detects libraries used, and creates 2 manifest files,
Gopkg.lock
andGopkg.toml
. - If there's a manifest file already, run
dep ensure
to create thevendor
folder and download the dependent files.
- This tool searches and detects libraries used, and creates 2 manifest files,
The summarized structure is as follows:
golang-hello-vendor
- src/
- hello.go
- hello/
- Gopkg.lock
- Gopkg.toml
- hello.go
- vendor/
- github.com/...
- golang.org/...
The following is the example code for the above:
hello.go
package main
import (
"fmt"
"hello"
)
// Main forwading to Hello
func Hello(args map[string]interface{}) map[string]interface{} {
fmt.Println("Entering Hello")
return hello.Hello(args)
}
hello/hello.go
package hello
import (
"os"
"github.com/sirupsen/logrus"
)
var log = logrus.New()
// Hello receive an event in format
// { "name": "Mike"}
// and returns a greeting in format
// { "greetings": "Hello, Mike"}
func Hello(args map[string]interface{}) map[string]interface{} {
log.Out = os.Stdout
res := make(map[string]interface{})
greetings := "world"
name, ok := args["name"].(string)
if ok {
greetings = name
}
res["golang-hello-vendor"] = "Hello, " + greetings
log.WithFields(logrus.Fields{"greetings": greetings}).Info("Hello")
return res
}
The vendor
folder may be created by the version control system, so it doesn't need to be saved separately. Only the manifest files need to be saved, but the vendor
folder needs to be included to create a compiled action.
If you want to use a third party library from the main
function, you need to move the main package files on the top level to the main
folder, and create the vendor
folder.