Go Actionを利用する

Cloud Functionsでは、Go Language(以下、Go)コードを実行させられるアクションコンテナーを提供します。Go 1.1バージョンを基本提供し、独立した環境でコードを実行することができます。

予めコンパイルしてZip形式でアップロードしたり、Web上でコードを編集して実行することができます。

Actionを作成する

まず、以下のように、名前と場所を含む"Hello World"を出力する簡単なGo Actionである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
}

Goコードは、1つ以上のGoソースファイルを有することができます。Goソースで作ったActionの入口点はMain Packageにある関数です。Main関数の基本名はMainであるが、ユーザーの選択によて別名に変更することができます。しかし、名前の開始点は常に大文字で表記されます。そして、そのMain関数は、次の説明のように、特定の形式で作らなければなりません。

main関数の形式

func Main(event map[string]interface{}) map[string]interface{}

GOコードは、複数の関数を含むことができるが、main関数はプログラムの開始点として必ず宣言されなければなりません。

上記で作成したコードで'hello'という名前のActionを作ります。

img

対応可能な形式

実行環境においては、次のような形式に対応します。

  • AMD64のアーキテクチャ用にコンパイルされたLinux ELFの実行ファイルの実行可能なバイナリー
  • AMD64のアーキテクチャ用にコンパイルされたLinux ELFの実行ファイルを含み、最上位にexec名の実行ファイルを含むzipファイル
  • Goでコンパイルされた単一のソースファイル
  • 最上位レベル(フォルダ)に実行バイナリーファイルを含まないzipファイルは、その後コンパイルされた実行されます。

GOOS=LinuxGOARCH=amd64で全てのGoに対応するプラットフォームで、正しい形式のバイナリーをクロスコンパイルすることができます。後述のように、事前コンパイル機能を利用して実行環境と同様のコンパイルを利用するほうがより安全です。

パッケージとvendorを利用してActionを作成する

コードを作成していると、1つのアクションファイル以外の依存ファイルを一緒にパッケージングしなければならない場合があります。このような場合、関連するファイルを1つに圧縮してパッケージングし、圧縮されたファイルを利用してパッケージングされたActionを作成することができます。

zip形式でActionを作る際、以下の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"のように呼び出します。それは、もしローカル開発環境でコンパイルする場合、ユーザーのGOPATHsrcの上位ディレクトリーを設定しなければならないことを意味します。もし、ユーザーが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フォルダを利用する

別のサードパーティーライブラリーを利用しなければならない場合、ランタイムはコンパイルする際、インターネットを介してそのライブラリーをダウンロードしません。vendorフォルダの構造を利用してダウンロードをし、配置しなければなりません。ここでは、depツールを利用する方法について説明します。

vendorフォルダは、srcフォルダとパッケージフォルダ、そしてvendorフォルダを含む必要があり、最上位フォルダで動作しません。もし、mainパッケージに含まれたファイルを利用するためには、最上位フォルダでないmainで明示された下位フォルダに配置しなければなりません。

例えば、ファイルsrc/hello/hello.goで以下のパッケージをimportする場合,

import "github.com/sirupsen/logrus"

vendorフォルダを作るためには、次の手順を行います。

  • depツールをインストールしてください。

  • src/helloフォルダに入って下さい。(srcフォルダではありません。)

    cd ./src/hello
    
  • DEPPROJECTROOT=$(realpath $PWD/../..) dep initを実行します。

このツールは、使われたライブラリーを探索/検知し、2つのマニフェストファイルGopkg.lockGopkg.tomlを作ります。既にマニフェストファイルがある場合には、dep ensureを実行すると、vendorフォルダが作られ、従属のファイルがダウンロードされます。

構造をまとめてみると、以下の通りです。

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フォルダを再度作成することができるため、別途保存する必要がありません。マニフェストファイルだけを保存してください。しかし、コンパイルされた状態でActionを作るためには、vendorフォルダを含む必要があります。

もし、main関数でサードパーティーライブラリーを利用したい場合には、最上位にあるmainパッケージのファイルをmainフォルダ内に移動し、vendorフォルダを作る必要があります。最上位フォルダは認識することができません。

基本パラメータを設定する

毎回Actionを実行する度にパラメータを転送する代わりに、特定のパラメータに基本値を指定することができます。上記で作成したhelloアクションのplaceパラメータに基本値を登録してみます。

img

Action実行時にパラメータを転送する

Actionの実行の際、入力でパラメータを転送することができます。Main関数に転送されるパラメータは、JSON object形式で転送されます。

パラメータは、Actionの実行の際に直接入力するか、JSON形式のファイルを作成して転送することができます。ファイルを通じてパラメータを転送する場合には、以下のようなJSON形式のファイルを作成する必要があります。

img

関連情報へ

下のガイドから関連情報をご確認いただけます。

に対する検索結果は~件です。 ""

    に対する検索結果がありません。 ""

    処理中...