GoLang

10分GO 16日目

goaっていうフレームワークについてお勉強。

あちこちのサイトを見ながら、何個か作ってみたんだけど・・なんかうまくいかない

今回はどうか・・

DSL言語

名前だけは聞いたことある・・

ドメイン固有言語

ある特定の領域(ドメイン)の問題を解決するために作られた言語。言語とは何かを記述するためのもの。

って Wikipedia 読んだけど、何言ってるか全然わからん・・

 

GO

今回のお題。GOのAPIサーバーを作る。

goa

goaをインストールする
$ pwd
/Users/mikke/go/src
$ ls
awesomeProject		golang.org		mywebapp
github.com		gopkg.in		todolist
gohandson		gopl.io-ch1-echo1	tweets-collection
$ go install github.com/goadesign/goa/goagen
$ cd goadesign/goa/goagen
$ go build

 

goaサービス用のフォルダを作る
$ mkdir -p $GOPATH/src/goa-adder/design

 

GoLnadでプロジェクトフォルダを開いて、GOファイル作成

↓これ、開くの間違えたの。$GOPATH/src/goa-adder/design じゃなくて、$GOPATH/src/goa-adder を開くのが正解。

design/design.goを作成する。

// designパッケージを定義する
// 名前はなんでも良い(designは慣例)
package design

// goaはGOで書かれているけどGOではない
import (
   . "github.com/goadesign/goa/design"
   . "github.com/goadesign/goa/design/apidsl"
)

// 匿名変数(アンスコ)を使ってAPIを宣言する
// API関数
//     API(APIの名前, 無名関数)
var _ = API("adder", func() {
   // プロパティにタイトルと説明文を書く
   Title("The adder API")
   Description("A teaser for goa")
   Host("localhost:8080")
   Scheme("http")
})

// 匿名関数を使ってResourceを宣言する
// Resource関数
//     Resource(お名前, 無名関数)
// プロパティ
//     リソースがサポートする全てのアクション
//     レスポンスでリソースを表示するために使用されるデフォルトのメディアタイプを指定する
var _ = Resource("operands", func() {
   // Action関数を宣言する
   //     HTTPメソッド, URL, エンドポイント, パラメーター
   Action("add", func() {
      Routing(GET("add/:left/:right"))
      Description("add returns the sum of the left and right parameters in the response body")
      Params(func() {
         // DSLの書き方らしい?
         // Param(<名前>, <型>, <説明> func() {
         //     バリデーション(省略可)
         //     default val(省略可)
         //     使用例(省略可)
         // })
         Param("left", Integer, "Left operand")
         Param("right", Integer, "")
      })
      Response(OK, "text/plain")
   })
})

 

そんなコマンドないよ?
$ goagen bootstrap -d goa-adder/design
-bash: goagen: command not found

って言われるの。

2時間悶々とした結果、GOPATHが通ってなかっただけだった・・・がーん。

パスを通したら goagen bootstrap -d goa-adder/design できた。

で、

$ pwd
/Users/mikke/go/src/goa-adder
$ ls
app		design		operands.go	tool
client		main.go		swagger

こんなのができている。

 

operands.go を編集する

/Users/mikke/go/src/goa-adder/operands.go こっちだよ

/Users/mikke/go/src/goa-adder/client/operands.go こっちじゃないよ

package main

import (
	"github.com/goadesign/goa"
	"goa-adder/app"
	"strconv"
)

// OperandsController implements the operands resource.
type OperandsController struct {
	*goa.Controller
}

// NewOperandsController creates a operands controller.
func NewOperandsController(service *goa.Service) *OperandsController {
	return &OperandsController{Controller: service.NewController("OperandsController")}
}
/* コメントして
// Add runs the add action.
func (c *OperandsController) Add(ctx *AddOperandsContext) error {
	// OperandsController_Add: start_implement

	// Put your logic here

	return nil
	// OperandsController_Add: end_implement
}
*/
// ここ追加
func (c *OperandsController) Add(ctx *app.AddOperandsContext) error {
	sum := ctx.Left + ctx.Right
	return ctx.OK([]byte(strconv.Itoa(sum)))
}

 

ビルドする。

おっけいぽい

 

GoLnad上でadder-cliをビルドしたらうまく実行できなかったので、ターミナルで実行。

これもうまくいかなくて、

Open a new console and compile the generated CLI tool:

公式サイトをよく読んだら、新しいターミナル開きなさいよ・・と。。

新しいターミナルで、もういっかい実行

$ cd $GOPATH/src/goa-adder/tool/adder-cli
$ go build
$ ls
adder-cli main.go

adder-cli できてるし。

それでは実行してみましょう。

$ ./adder-cli add operands /add/1/2
2019/03/14 23:48:56 [INFO] started id=D45GGgDa GET=http://localhost:8080/add/1/2
2019/03/14 23:48:56 [INFO] completed id=D45GGgDa status=200 time=5.192374ms

お、動きました〜

 

$ ./adder-cli add operands --left=1 --right=2
2019/03/14 23:52:38 [INFO] started id=1516okXQ GET=http://localhost:8080/add/1/2
2019/03/14 23:52:38 [INFO] completed id=1516okXQ status=200 time=3.995963ms

これも。コピぺだけど。

 

$ ./adder-cli add operands add/1/あ
2019/03/14 23:55:34 [INFO] started id=hRU45PBR GET=http://localhost:8080/add/1/あ
2019/03/14 23:55:34 [INFO] completed id=hRU45PBR status=400 time=21.12531ms
error: 400: {"id":"jUC34HqR","code":"invalid_request","status":400,"detail":"invalid value \"あ\" for parameter \"right\", must be a integer","meta":{"expected":"integer","param":"right","value":"あ"}}

検証もばっちり。

 

おわり

swaggerとかまでやってみたかったけど、タイムオーバー。

今週、あちこちのブログ見てやったけどできなくて、中島聡氏の公式ドキュメントをまず見ましょう〜って言葉を思い出して、英語できないけどがんばって読んだわ・・。あと、tenntennさんがGoogle翻訳かけるときはGOの部分をJavaとかに置き換えてみ・・ていうのもなかなか使える。

昼間は昼休みあっという間だし、帰宅したらごはん作んなきゃなんないし、夜、1〜2時間しか時間とれないし、家族のじゃまがめっちゃ入るし、役員のお手伝いやらないとやんないし・・他の言語とか技術にも興味あるし・・なかなか進まないけど、ゆるゆると継続していくわ〜

 

-GoLang