スキップしてメイン コンテンツに移動

Goa Hello World

この章では、goaを使ってHello World!と表示させるAPIのサンプルを作ってみます。
何となくgoaとはどういうものか、感覚が掴めると思います。

セットアップ

サンプルを作る土台作りをしましょう。
  • gvm
  • golang 1.7.5
  • goa

の3つをインストールします。
※既にインストールしている場合は読み飛ばしてください

gvmをインストール

サンプルはGoのバージョン1.7.5を使って作っていきます。
 それではまず、Goのバージョン管理ツールであるgvmをインストールしましょう。

$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
$ source ~/.gvm/scripts/gvm
$ gvm version

これで、gvmのバージョンが表示されたら成功です。

Goをインストール

gvmを使ってGoをインストールします。
通常、gvmを使ってGoをインストールする場合は

$ gvm install go1.7.5

で良いのですが、Mac OSがSierra以上だと、コンパイルが失敗します。
このブログを執筆している時点での話なので、そのうち解消しているかも知れません

なので-Bオプションを付けて、バイナリのみをインストールします。

$ gvm install go1.7.5 -B
$ gvm use go1.7.5
$ go vesion

Goのバージョンが表示されたら成功です。

goaのインストール



$ go get -u github.com/goadesign/goa/...
$ goagen version

goagenのバージョンが表示されたら成功です。

実装

セットアップが完了したところで、goaを使ってアプリケーションのデザインをしていきます。
 作業ディレクトリはgoasampleとしましょう。

$ cd $GOPATH/src
$ mkdir goasample
$ cd goasample

また、goaを進めるに当たって、
  • 自分が何のファイルを実装する事になるのか
  • どういうファイルが自動で作られるのか
の変遷を見るために、gitで管理していきましょう。

$ git init

design/design.go

goaのAPIデザインを定義していくデザインファイルを作成します。

$ mkdir design
$ vim design/design.go

そして、以下のソースコードを実装します。

package design

import (
    . "github.com/goadesign/goa/design"
    . "github.com/goadesign/goa/design/apidsl"
)

var _ = API("goasample", func() {
    Title("Hello World API")
    Description("goaでハローワールドを表示するサンプルアプリケーションです")
    Host("localhost:8080")
    Scheme("http")
})

var _ = Resource("helloworld", func() {
    Action("show", func() {
        Routing(GET(""))
        Description("ハローワールドを表示します")
        Response(OK, "text/plain")
    })
})

ここで一旦、ソースコードをgitのstageにあげましょう。

$ git add .
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached ..." to unstage)

        new file:   design/design.go

コード生成

デザインファイルができたら、そこからGoのソースコードを生成します。

goagen bootstrap -d goasample/design

goagenで、様々なファイルが作られたと思います。

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached ..." to unstage)

        new file:   design/design.go

Untracked files:
  (use "git add ..." to include in what will be committed)

        app/
        client/
        helloworld.go
        main.go
        swagger/
        tool/

  • app/
  • client/
  • helloworld.go
  • main.go
  • swagger/
  • tool/

という、4つのディレクトリと、2つのファイルが生成されましたね。
それぞれの意味は、次章にて説明していきます。

ビルド

ここまできたら、もうビルドできる状態です。

$ go build

するとgoasampleという成果物(実行ファイル)が生成されました。
実行してみましょう。

$ ./goasample
2017/05/28 17:11:53 [INFO] mount ctrl=Helloworld action=Show route=GET /
2017/05/28 17:11:53 [INFO] listen transport=http addr=:8080

ポート8080でlistenしてますね。
curlでアクセスしてみましょう

$ curl "http://localhost:8080"

何も表示されていませんね。
ビジネスロジックを何も書いていないため、レスポンスボディは空です。
しかし、goasampleは何やら、ログを出力しています。

2017/05/28 17:11:53 [INFO] mount ctrl=Helloworld action=Show route=GET /
2017/05/28 17:11:53 [INFO] listen transport=http addr=:8080
2017/05/28 17:11:59 [INFO] started req_id=w7jBWswQUi-1 GET=/ from=::1 ctrl=HelloworldController action=show
2017/05/28 17:11:59 [INFO] headers req_id=w7jBWswQUi-1 User-Agent=curl/7.51.0 Accept=*/*
2017/05/28 17:11:59 [INFO] completed req_id=w7jBWswQUi-1 status=0 bytes=0 time=130.291µs ctrl=HelloworldController action=show

アクセスがあったように見えます。
疎通はできているようです。
しかし、これだけじゃAPIが作られているのか不安になりますので、 curl -v でHTTPヘッダを確認してみましょう。

$ curl -v "http://localhost:8080"
* Rebuilt URL to: http://localhost:8080/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.51.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 28 May 2017 08:15:05 GMT
< Content-Length: 0
< Content-Type: text/plain; charset=utf-8
<
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact

HTTP/1.1 200 OKと返ってきていればAPIの疎通確認としては十分です。

ビジネスロジックの実装

レスポンスボディを返すため、ロジックを実装します。
変化を見るため、またソースコードをgitのstageに追加しましょう。

$ git add .
$ vim helloworld.go

helloworld.goを開くと、以下のメソッドがあると思います。

// Show runs the show action.
func (c *HelloworldController) Show(ctx *app.ShowHelloworldContext) error {
    // HelloworldController_Show: start_implement

    // Put your logic here

    // HelloworldController_Show: end_implement
    return nil
}

先ほどのcurlでアクセスした時、ここのメソッドが呼ばれる事になります。
returnで返す箇所を、以下のように変えてみましょう。

 ctx.OK([]byte("Hello World!\n"))

git diffで差分を見てみると、以下の差分が表示されます。

-     return nil
+     return ctx.OK([]byte("Hello World!\n"))
それでは、起動しているgoasampleをCtrl +Cで止めて、ビルド・起動して見ましょう。

$ go build
$ ./goasample

またcurlでアクセスして見ると

$ curl "http://localhost:8080"
Hello World!

Hello World!と表示されましたね!成功です!

感想

如何でしたでしょうか。
今回のサンプルは非常に小さなアプリケーションですが、
非常に簡単だったのではないでしょうか。 
ビジネスロジック以外の処理は、デザインした通りに勝手に生成してくれます。
次章では、自動生成されるファイルの説明をしていきます。

コメント

このブログの人気の投稿

goa request parameters

Request この章では、APIリクエストのデザインについて説明していきます。 リクエストには、主に 3種類 、データの渡し方があります。 URLのPathに含まれる、リソースを識別するものとしてのパラメータ Queryパラメータ(GETで良く使われる、?に続く文字列ですね) リクエストボディ 他にも HTTPリクエスト という点では、HTTPヘッダも存在しますが、 HTTPヘッダはリクエストパラメータというより、 リクエストの形式や認証などに使われる、メタデータ的な意味合いがあるため この章では扱いません。 それでは、それぞれの詳細を見ていきましょう。 Pathパラメータ RESTFulなAPIを扱うとき、良く出てくる /user/ :id -> /user/ 100 /product/ :category/ :product_id -> /product/book /300 のような、URLに含まれるパラメータですね。 正式名称は何というのでしょうか。 このパラメータは、 Resource を識別するために使われます。 Queryパラメータで識別しても良いのですが、Queryパラメータはどちらかというと、 APIの振る舞い・挙動を変える意味合いがあります。 この辺の考えは、RESTfulというアーキテクチャの話になってくるため、ここでは割愛します。 それでは実装してみましょう。 先ほどまでのソースコードを一旦、コミットします。 $ git add . $ git commit -m "first commit" そして、デザインファイルにResourceを追加します。 var _ = Resource( "products" , func() { Action( "show" , func() { Routing(GET( "products/:category_id/:product_id" )) Params (func() { Param( "category_id" , Integer , "カテゴリID&qu

goa -Golang Web Application Framework-

 Webアプリケーションフレームワーク goa goaとは、GolangでWebアプリケーションを構築していくフレームワークです。 今流行りのマイクロサービスやAPIサーバを 早急に構築 できます。(HTMLを返すWebサーバももちろん、実装可能です) 早急 といった言葉を使ったのは、Webアプリケーションを構築する際の ルーティング リクエストパラメータの定義 レスポンスパラメータの定義 パラメータのバリデーション コントローラの定義 といった、ビジネスロジック以外の土台部分を自動で生成してくれて、 ビジネスロジックの実装に専念できるからです。 自動生成といっても、思い描いたものが勝手にできる訳ではなく、 goa独自のDSLを記述してアプリケーションの仕様を定義する( デザイン する) 必要があります。 goaではアプリケーションの枠組みを、 design.go (デザインファイル)というAPIの定義書を作って生成していきます。 DSLを覚える学習コストはありますが、それに見合った以上の働きをしてくれます。 Webアプリケーションのフレームワークとして有名な Ruby on Rails も、 お作法を知らないと、レールから外れた実装をする事になり複雑な実装になってしまいます。 が、Railsは世界中で使われてる有名なフレームワークとなっています。 その学習コスト以上に見合った以上の働きがあるからでしょう。 goaは、ビジネスロジックに没頭できる点において、 Railsに匹敵できるほどポテンシャル を持っていると思います。 もちろん、RubyではなくGo言語なので、言語仕様上の違いがあり単純に比較はできません。 このブログでは、自分の学習結果のアウトプットとして、 goaについての紹介を連載 していきたいと思います。

自動生成されるファイル

自動生成されるファイル 先ほどのサンプルアプリケーションの作業ディレクトリには、 以下のファイル・ディレクトリがあります。 design/ app/ client/ swagger/ tool/ helloworld .go main .go 一つ一つ見ていきましょう。 生成物一覧 design/design.go これは、最初に実装したデザインファイルになります。 アプリケーションの枠組みを決める設計図のようなものです。 goa独自の DSL(domain-specific language) を使って、APIの仕様を定義していきます。 app/ ここには、デザインされたアプリケーションの、実際に動くコードが生成されていきます。 基本的に、このディレクトリに格納されたファイルは 編集不可(できるけど、しちゃだめ) と考えて良いです。 プログラマが追加実装しても、次にまたコード生成した場合、プログラマの追加実装は上書きされて消されてしまいます。 app/contexts.go コンテキストが実装されています。 goaでは基本的に、API一つ一つに対して対応するコンテキストが実装されていきます。 コンテキストとは、HTTPリクエストを受け付けてからレスポンスを返すまで、 一連の流れが終わるまでの状態を表します。 2つのHTTPリクエストがあった場合、コンテキストは別々のオブジェクトとなります。 どのHTTPリクエストなのかを識別できるような、リクエスト毎の固有情報ですね。 コンテキストは3つのプロパティを持ち、 type ShowHelloworldContext struct { context . Context * goa . ResponseData * goa . RequestData } Go標準のContextと、リクエスト・レスポンスを持っています。 app/controllers.go コントローラの interface が定義されています。 コントローラとは、Webアプリケーションでよく使われるデザインパターン MVC(Model View Controller) のControllerです。 コントローラ