- 印刷する
- PDF
Go
- 印刷する
- PDF
Classic/VPC環境で利用できます。
Go(Go Language)形式のアクションを作成して様々な方法で活用する方法と、そのユースケースを紹介します。
アクション作成
Goコードは、1つ以上の Goソースファイルを持つことができます。Goソースで作成した Actionのエントリーポイントは、Main Packageにある関数です。Main関数のデフォルト名は Mainですが、ユーザーの選択により他の名前に変更できます。ただし、名前の先頭は常に大文字で表記されます。また、この Main関数は以下の説明のような形で作成する必要があります。
func Main(event map[string]interface{}) map[string]interface{}
Goで作成したコードは複数の関数を含めますが、main
関数はプログラムのエントリーポイントとして宣言される必要があります。この点を考慮して名前と場所を含めて「Hello World」を出力する Go形式の簡単なサンプルコードの「hello
」は、次の通りです。
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
}
上記で作成したコードを使用してコンソールで「hello」という名前のアクションを作成する手順は、次の通りです。
サポート可能な形態
実行環境でサポート可能な形態は、次の通りです。
- AMD64アーキテクチャ用にコンパイルされた Linux ELF実行ファイルの実行可能なバイナリ
- AMD64アーキテクチャ用にコンパイルされた Linux ELF実行ファイルが含まれていて、最上位に
exec
という名前の実行ファイルが含まれている zipファイル - Goでコンパイルされた単一ソースファイル
- 最上位レベル(フォルダ)に実行バイナリファイルを含まない zipファイルは、その後にコンパイルされて実行
GOOS=Linux
と GOARCH=amd64
ですべての Goをサポートするプラットフォームで、有効な形式のバイナリをクロスコンパイルできます。事前コンパイル機能を使用して実行環境と同じコンパイラを使用した方がより安全です。
Go Modulesを使ってアクションを作成
go1.19バージョンで外部ライブラリを使うためには、Go Modules
を使います。Go Modules
を使用しない場合、ソースコードを直接含める必要があります。
以下は、go mod
を使ってアクションで下記のパッケージを取得する方法のステップバイステップガイドです。この方法はインターネット通信が可能である必要があり、VPC環境の場合は NAT G/Wの設定が必要です。NAT G/Wに関する詳細は、NAT Gatewayご利用ガイドをご参照ください。
import "github.com/rs/zerolog"
- 新しいモジュールの初期化
次のコマンドを実行して新しいモジュールを初期化します。このコマンドを実行すると、go.mod
ファイルが作成されます。
go mod init <module>
main.go
の作成
下記のサンプルコードを参照して 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
}
- 依存関係のインポート
以下のコマンドを実行して go.mod
ファイルを更新し、go.sum
ファイルを作成します。
go get github.com/rs/zerolog@v1.19.0
- アクションパッケージングとアップロード
以下のコマンドを実行してパッケージを圧縮し、アップロードしてアクションを作成します。
zip -r action.zip go.mod go.sum main.go
パッケージと vendor
を使ってアクションを作成
コードを作成していると、1つのアクションファイル以外に依存ファイルを一緒にパッケージングする必要がある場合があります。このような場合、関連するファイルを1つのファイルに圧縮してパッケージ化し、圧縮されたファイルを利用してアクションを作成できます。
zipファイルを利用してアクションを作成する場合、可能な3つの形式は次の通りです。
main
パッケージの中にすべての機能を実装した場合main
パッケージの他に一部パッケージを分離して構成した場合- 機能の実装のために、外部に依存関係にある部分を含む形で実装した場合(include third party dependencies)
すべての機能が基本パッケージにある場合、すべてのソースファイルを zipファイルの最上位レベルに配置します。
パッケージフォルダを使用する
一部機能がメイン関数の実行部分と異なるパッケージに属する場合、hello/
のような形でパッケージ名を作成してフォルダをパッケージングする必要があります。パッケージングのユースケースは、次の通りです。
golang-main-package/
- src/
- main.go
- hello/
- hello.go
- hello_test.go
テストを実行してエラーなしで編集するには、src
フォルダを使用する必要があります。基本パッケージの内容は src/
の下位に、hello
パッケージのソースコードは hello/
フォルダに配置します。しかし、使用するためには下位パッケージを import "hello"
のようにインポートする必要があります。これは、ローカル開発環境でコンパイルする場合、ユーザーの GOPATH
に src
の上位ディレクトリを設定する必要があることを意味します。 ユーザーが VSCodeといったエディタを使用する場合、go.inferGopath
オプションを有効にする必要があります。
ソースを送る際は、最上位ディレクトリではなく、src
フォルダの内容を以下のように圧縮してください。
cd src
zip -r ../hello.zip *
cd ..
上記の内容に対するサンプルコードは、次の通りです。
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"}
}
vendor
フォルダを使用する
他の3rd-partyライブラリを使用する場合、ランタイムはコンパイルする際にインターネットを通じてそのライブラリをダウンロードするのではなく、vendor
フォルダ構造を使用してダウンロードして配置する必要があります。ここでは、dep
ツールを使用する方法について説明します。
vendor
フォルダに src
フォルダ、パッケージフォルダ、vendor
フォルダが含まれている必要があります。最上位フォルダでは動作しません。main
パッケージに含まれたファイルを使用するには、最上位フォルダではなく main
と明示された下位フォルダに配置します。例えば、ファイル src/hello/hello.go
で以下のようなパッケージを importする必要があるとします。
import "github.com/sirupsen/logrus"
このような場合、vendor
フォルダを作成するには、以下の手順に従ってください。
depツールをインストールします。
src/hello
フォルダに移動します。cd ./src/hello
src
フォルダではなくsrc/hello
であることにご注意ください。
DEPPROJECTROOT=$(realpath $PWD/../..) dep init
を実行します。- このツールは、使用されたライブラリを探索・検知して2つのマニフェストファイル
Gopkg.lock
、Gopkg.toml
を作成 - 既にマニフェストファイルがある場合、
dep ensure
を実行するとvendor
フォルダが作成され、依存ファイルをダウンロード
- このツールは、使用されたライブラリを探索・検知して2つのマニフェストファイル
構造をまとめると、次の通りです。
golang-hello-vendor
- src/
- hello.go
- hello/
- Gopkg.lock
- Gopkg.toml
- hello.go
- vendor/
- github.com/...
- golang.org/...
上記の内容に対するサンプルコードは、次の通りです。
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
}
バージョニングシステムで vendor
フォルダを再度作成できるので、別途保存する必要はありません。マニフェストファイルだけ保存すればいいですが、コンパイルされた状態でアクションを作成するには、vendor
フォルダを含める必要があります。
main
関数で3rd-partyライブラリを使用する場合、最上位にある mainパッケージのファイルを main
フォルダに移動させて vendor
フォルダを作成する必要があります。