Goa

スポンサーリンク

Goaとは

GoaはGoのフレームワークの1つで、REST APIに特化しています。
ビジネスロジックの開発に専念できるよう設計されており、デザインファイルを定義することで、サーバ・クライアント・ドキュメント(swagger)の3つを生成することができるという特徴を持っています。

インストール

Goが使える状態になっていることは前提として、下記でインストールできます。

% go get -u goa.design/goa/v3
% go get -u goa.design/goa/v3/...

ちなみに、この時点で私ははまりまくりました。。。。
興味ある方は下記をどうぞ。

Goaのインストールではまった件
かなりしょーもない話なのですが、もしかしたら同じような人が出てくるかもしれないので恥を忍んで記録を残しておきます。 Goa を使いたいと思って、自分の Mac 環境に Goa をインストールしようとしました。Go 自体は既に使える状態になっ...

Getting Started

公式サイトに Getting Started というページがあるので、これを試してみました。
https://goa.design/learn/getting-started/

% mkdir -p test/design
% cd test
% go mod init calc
go: creating new go.mod: module calc

必要であればここで Goa を最新版に更新しておきます。

% go get -u goa.design/goa/v3
% go get -u goa.design/goa/v3/...

下記のようなデザインファイルを作成します。

package design

import (
	. "goa.design/goa/v3/dsl"
)

var _ = API("calc", func() {
	Title("Calculator Service")
	Description("Service for adding numbers, a Goa teaser")
    Server("calc", func() {
        Host("localhost", func() {
            URI("http://localhost:8000")
            URI("grpc://localhost:8080")
        })
    })
})

var _ = Service("calc", func() {
	Description("The calc service performs operations on numbers.")

	Method("add", func() {
		Payload(func() {
			Field(1, "a", Int, "Left operand")
			Field(2, "b", Int, "Right operand")
			Required("a", "b")
		})

		Result(Int)

		HTTP(func() {
			GET("/add/{a}/{b}")
		})

		GRPC(func() {
		})
	})

	Files("/openapi.json", "./gen/http/openapi.json")
})

Goaでコードを generate します。

% goa gen calc/design
gen/calc/client.go
gen/calc/endpoints.go
gen/calc/service.go
gen/grpc/calc/client/cli.go
gen/grpc/calc/client/client.go
gen/grpc/calc/client/encode_decode.go
gen/grpc/calc/client/types.go
gen/grpc/calc/pb/calc.proto
gen/grpc/calc/server/encode_decode.go
gen/grpc/calc/server/server.go
gen/grpc/calc/server/types.go
gen/grpc/cli/calc/cli.go
gen/http/calc/client/cli.go
gen/http/calc/client/client.go
gen/http/calc/client/encode_decode.go
gen/http/calc/client/paths.go
gen/http/calc/client/types.go
gen/http/calc/server/encode_decode.go
gen/http/calc/server/paths.go
gen/http/calc/server/server.go
gen/http/calc/server/types.go
gen/http/cli/calc/cli.go
gen/http/openapi.json
gen/http/openapi.yaml

ちなみに、上記で、、、

exit status 1
failed to run protoc: exec: "protoc": executable file not found in $PATH:

このようにエラーが出た場合には、protobuf をインストールする必要があります。
Mac であれば、Homebrew でインストールできます。

% brew install protobuf

次に、下記のようにして example をダウンロードします。

% goa example calc/design
calc.go
cmd/calc-cli/grpc.go
cmd/calc-cli/http.go
cmd/calc-cli/main.go
cmd/calc/grpc.go
cmd/calc/http.go
cmd/calc/main.go

これで基本的には準備は整ったのですが、 add API の内容が足算になっていないので、下記のように calc.go を正しい内容に修正します。

func (s *calcsrvc) Add(ctx context.Context, p *calc.AddPayload) (res int, err error) {
  return p.A + p.B, nil
}

これですべて用意ができたのでビルドします。
クライアントとサーバの両方をビルドします。

% go build ./cmd/calc && go build ./cmd/calc-cli
go: finding module for package github.com/grpc-ecosystem/go-grpc-middleware
go: downloading github.com/grpc-ecosystem/go-grpc-middleware v1.2.0
go: found github.com/grpc-ecosystem/go-grpc-middleware in github.com/grpc-ecosystem/go-grpc-middleware v1.2.0

確認

サーバ実行

% ./calc
[calcapi] 01:28:20 HTTP "Add" mounted on GET /add/{a}/{b}
[calcapi] 01:28:20 HTTP "./gen/http/openapi.json" mounted on GET /openapi.json
[calcapi] 01:28:20 serving gRPC method calc.Calc/Add
[calcapi] 01:28:20 HTTP server listening on "localhost:8000"
[calcapi] 01:28:20 gRPC server listening on "localhost:8080"

ここでクライアントを下記のように実行すると、足算した結果が返ってくることが確認できます。

% ./calc-cli --url="http://localhost:8000" calc add --a 1 --b 2
3

サーバ側のログには下記のように出力されました。

[calcapi] 01:28:50 id=vURfjlw7 req=GET /add/1/2 from=127.0.0.1
[calcapi] 01:28:50 id=vURfjlw7 status=200 bytes=2 time=96.551µs

gRPC

ちなみに、、、、上記の例では gRPC にも対応しており、クライアントで下記のように実行すると試せるはずなのですが、、、

./calc-cli --url="grpc://localhost:8080" calc add --message '{"a": 1, "b": 2}'

なぜか下記のようにエラーが出てうまくいっていません(/_\*)

rpc error: code = Unavailable desc = connection closed

たぶん非常に根本的なことが問題なのだと思うのですが、もしご存知の方がいらっしゃれば教えてください(/_\*)

コメント

タイトルとURLをコピーしました