Golangのvendor管理周りでちょっとハマった

vendor管理 / glide

Goは1.5あたりからプロジェクトのvendorディレクトリ内のパッケージをグローバルより優先して見に行く設定にできる。

export GO15VENDOREXPERIMENT=1

 

プロジェクト毎のvendor管理のためにパッケージ管理ツールglide などを使うと、基本的にプロジェクトのvendor内に3rdパーティのパッケージがインストールされていく。

glide get した依存モジュールはglide.yamlに自動追記され、vendor以下がバージョン管理対象外でも glide install で別環境でも復元できるようになる。

要するに「プロジェクトごとにモジュールのバージョンとか固定しようぜ」っていう、package.json的なものに近い。

サブパッケージ内からvendor内のパッケージが見つからない

そこで、main.goがsubpackage内のモジュールを呼ぶこういう感じになるとする。
 


projectName │  ├── subpackage │   ├── example │   │   └── example.go │   └───example2 │      └── example2.go ├── glide.lock ├── glide.yaml ├── main.go └── vendor    ├── github.com ├── aws ....

 

上記の構成でいうexample.goからawsをimportしたところ、cannot find package...で怒られた。
結論から言うと、原因はここにかいてあった通りだった。

ダメ

main.go

import (
    "./subpackage/sub"
)
func main() {
    sub.Run()
}

OK

main.go

import (
    "projectName/subpackage/sub"
)
func main() {
    sub.Run()
}

下だと動く。
相対パスでのimportで入れたパッケージからもグローバルのパッケージは呼べたので油断していたが、vendor内にアクセスするには、対象がそのプロジェクトの一部だということを明示しないといけない?っぽい。

Read More

Golang or NodeJSで AWS Step Functions のActivityを書く

AWS Step Functionsによるピタゴラスイッチの終点で、「通常のEC2上でStep Functionsを待ち受け、RDS等になんか処理をするためのタスク」を書いている。

{
  TaskToken:xxxxx
  Input:<前段のタスクで処理したresponse>
}

ワーカーを作動させていると、こういう感じのデータがStepFunctionsから渡ってくるので、それを元に好きに処理して、SuccessやFailureリクエストをStep Functions側に返せばいい。
とりあえずDBへの登録処理とか、データの読み取りなしで実装してみる。

NodeJS

単純にNodeJSでやるならこういう感じ。

src/worker.ts

const AWS = require("aws-sdk");

const stepfunctions  : AWS.StepFunctions = new AWS.StepFunctions({
    apiVersion: '2016-11-23',
    region : "ap-northeast-1"
});


(async ()=>{
    while (1) {
        await new Promise(async (resolve) => {
            const stepFunctionParam = {
                activityArn: 'arn:aws:states:ap-northeast-1:xxxxxxx:activity:StepFunction-Called', /* required */
            };

            const data = await stepfunctions.getActivityTask(stepFunctionParam).promise();

            if (data != null && data.taskToken != null){
                console.log(data)

         /* ... Do Something !!!!!!! */

                const sendParams = {
                    output: "true", /* required */
                    taskToken: data.taskToken, /* required */
                };   

                await stepfunctions.sendTaskSuccess(sendParams).promise()

            }
            resolve();
        }).catch(error => console.error(error))
    }
})()

 
走れ。
 

AWS_PROFILE=my_aws_profile NODE_ENV=test node build/worker.js

 

タスク部分並列処理にしたかったらawaitやらresolveの位置いじっておく。
とりあえずNodeJSで動作確認したが、この手のコードはgolangがポ〜タビリティ高くて良さそうなので、次はGo言語の入門がてら書いてみる。

Go

あとgoのパッケージマネージャツール(vendor管理)glideも使ってみた。

glide create
glide get github.com/aws/aws-sdk-go

しておく。

main.go

package main

import (
    "fmt"
    "github.com/aws/aws-sdk-go/service/sfn"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/aws"
    "time"
)

func asyncTask(sfnSession *sfn.SFN , resp *sfn.GetActivityTaskOutput){

        /* ... Do Something !!!!!!! */

    params := &sfn.SendTaskSuccessInput{
        Output:    aws.String("true"),      // Required
        TaskToken: resp.TaskToken, // Required
    }
    sfnSession.SendTaskSuccess(params)

}

func loop() {

    awsConfig :=  &aws.Config{Region: aws.String("ap-northeast-1")}

    sess, err := session.NewSession(awsConfig)
    if err != nil {
        fmt.Println("failed to create session,", err)
        return
    }

    sfnSession := sfn.New(sess)

    params := &sfn.GetActivityTaskInput{
        ActivityArn: aws.String("arn:aws:states:ap-northeast-1:xxxxxxxxx:activity:StepFunction-Called"), // Required
    }
    resp, err := sfnSession.GetActivityTask(params)

    if err != nil {
        fmt.Println(err.Error())
        return
    } else if resp.TaskToken != nil {
        fmt.Println("success")

        // 並列処理
        go asyncTask(sfnSession , resp)
    }

    fmt.Println(resp)

}

func main() {

    for {
        loop()
    }

}

 
走れ。

AWS_PROFILE=my_aws_profile go run main.go

awsのconfigとかloopの外でよかったかな。
Go初めてなので参照周りやセッションとかもうちょっと調べる。

 

Read More

CompileDaemon を使ってオートリロード

auto-reload は色々あるのですが、たまたま見つけた、CompileDaemon を使ってみました。

上から5番目(2017年01月13日時点)ということで、まぁまぁいいんではないでしょうか。

% go get github.com/githubnemo/CompileDaemon
% go install github.com/githubnemo/CompileDaemon

で、インストールすると、CompileDaemon というプログラムが出来上がります。

オートリロードさせたいプログラムがある場所へ移動して、以下のように使います。

% CompileDaemon -command="./app_name" -include="*.go"

“./app_name” のところは、build したときに出来上がるファイル名を指定します。

“-include=” を指定することで、*.go 以外のファイルが更新されても無視します。

なかなか簡単に使えて良い感じです。

Read More

Go言語 関数の色々

この記事はWanoグループ Advent Calendar 2016の24日目の記事です。

Goの関数宣言方法

package main
import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

//普通の使い方
func Abs(v Vertex) float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

//オブジェクトにメソッドを追加する
func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

//自分のオブジェクトを作って、そこにプリミティブ型のメソッドを追加する
type MyFloat float64
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

func main() {
    v := Vertex{6, 8}
    f := MyFloat(-10.3)
    fmt.Println("v.Abs():",v.Abs())
    fmt.Println("Abs(v):",Abs(v))
    fmt.Println(f.Abs())
}

Goは、関数の引数として関数をわたすことができる。

package main
import (
    "fmt"
    "math"
)

/*
funinside func(float64, float64) float64 ==> 関数の引数
  関数名     引数1,  引数2   戻り値
*/
func compute(funinside func(float64, float64) float64 ,x,y float64) float64 {
    return funinside(x,y)
}

func add(x,y float64) float64 {
    return x+y
}
/*
compute (関数の引数,引数A,引数B)  関数替わり可能
*/
func main() {
    fmt.Println(compute(add,3,3))      //=> 3+3 
    fmt.Println(compute(math.Pow,3,3)) //=> 3^3
}

結果:
6
27

クロージャの使い方

package main
import "fmt"
// fibonacci is a function that returns a function that returns an int.
func fibonacci() func() int {  //匿名関数
    a, b := 0, 1
    return func() int {
        a, b = b, a+b  // (a = b), (b = a + b) 同時実行の意味 =>
        /* 同じコード
        c:= a
        a = b
        b = c + b
        */
        return a
    }
}

func main() {
    f := fibonacci()
    for i := 0; i &lt; 10; i++ {
        fmt.Print(f()," ")
    }
}

結果:
1 1 2 3 5 8 13 21 34 55

Read More