その2 ファイル分割してみる - golang製Web Framework 「echo」事始め
続き
前回の予告どおり、echoのサンプルプロジェクトのcrudモジュールについて、ソースファイルの分割をしてみる。
なお、普段からgolangを書いている人にとってはつまらない内容かもしれない。
けれども、なかなかどうしてimport何かではまったりして楽しかった。
ディレクトリ構成
こんな感じにしてみた
$ tree crud ├── handler │ ├── create.go │ ├── delete.go │ ├── list.go │ └── update.go ├── model │ └── user.go └── router.go
分割
server.go から router.go へ
server.go
は router
だけをまとめて、 router.go
とした。
router.go
package main import ( "github.com/labstack/echo" "github.com/labstack/echo/middleware" "./handler" ) func main() { e := echo.New() // Middleware e.Use(middleware.Logger()) e.Use(middleware.Recover()) // Routes e.GET("/users", handler.ListUser) e.GET("/users/:id", handler.GetUser) e.POST("/users", handler.CreateUser) e.PUT("/users/:id", handler.UpdateUser) e.DELETE("/users/:id", handler.DeleteUser) // Start server e.Logger.Fatal(e.Start(":1324")) }
modelディレクトリ
modelディレクトリはその名の通り、モデルを格納している。
model/user.go
package model type ( User struct { ID int `json:"id"` Name string `json:"name"` } ) var ( Users = map[int]*User{} Seq = 1 )
var (
Users = map[int]*User{}
Seq = 1
)
は永続層で、本来DBに置き換わる領域。
handlerディレクトリ
handler
という名前はサンプルから取った名前。ビジネスロジックを格納する領域としており、 Service
とした方が良いかもしれない。
それぞれCRUDの役割を持つロジックを定義している。
$ tree crud ├── handler │ ├── create.go │ ├── delete.go │ ├── list.go │ └── update.go
create.go
package handler import ( "net/http" "github.com/labstack/echo" "../model" ) func CreateUser(c echo.Context) (err error) { u := &model.User{ ID : model.Seq, } if err := c.Bind(u); err != nil { return err } model.Users[u.ID] = u model.Seq++ return c.JSON(http.StatusCreated, u) }
router.go
の e.POST("/users", handler.CreateUser)
にて下記の様なPOST リクエストを受け取り、データを格納する。
curl -v POST -H "Content-Type: application/json" "http://localhost:1324/users" -d '{ "id" : 1, "name" : "Anthony Kiedis" }'
modelは ./model
というようにimportする。
GOPATH配下の場合は絶対パスを指定するのがお作法らしいが、今回の場合はGOPATH配下に構築はしていないので、相対パスで書いてしまっている。
ハマったコト
ID : model.Seq,
の末尾に ,
が必要な理由が分からなかった…(削除するとコンパイルエラー)
update.go
package handler import ( "net/http" "strconv" "github.com/labstack/echo" "../model" ) func UpdateUser(c echo.Context) (err error) { u := new(model.User) if err := c.Bind(u); err != nil { return err } id, _ := strconv.Atoi(c.Param("id")) model.Users[id].Name = u.Name return c.JSON(http.StatusOK, model.Users[id]) }
router.go
の e.PUT("/users/:id", handler.UpdateUser)
にて下記の様なPUT リクエストを受け取り、データを更新する。
curl -v -X PUT -H "Content-Type: application/json" "http://localhost:1324/users/1" -d '{ "name" : "Anthony Kiedis at Red Hot Chili Peppers" }'
ハマったコト
Golang/echoとは直接関係ないのだけど、Elasticsearchをcurlで触っていた時はコンテントタイプは不要だった。
しかし、今回 -H "Content-Type: application/json"
をちゃんと指定しないと、正しくJSONパラメータとして渡せなかった。
まあコレが普通なのだけど、イマイチ・・・。
list.go
package handler import ( "net/http" "strconv" "github.com/labstack/echo" "../model" ) func GetUser(c echo.Context) (err error) { id, _ := strconv.Atoi(c.Param("id")) return c.JSON(http.StatusOK, model.Users[id]) } func ListUser(c echo.Context) (err error) { return c.JSON(http.StatusOK, model.Users) }
router.go
の e.GET("/users", handler.ListUser)
や e.GET("/users/:id", handler.GetUser)
にて、下記の様なGET リクエストを受け取り、データを取得する。
curl -i -v GET "http://localhost:1324/users" curl -i -v GET "http://localhost:1324/users/1"
delete.go
package handler import ( "log" "net/http" "strconv" "github.com/labstack/echo" "../model" ) func DeleteUser(c echo.Context) (err error) { log.Println(model.Users) id, _ := strconv.Atoi(c.Param("id")) delete(model.Users, id) log.Println(model.Users) return c.NoContent(http.StatusNoContent) }
router.go
の e.DELETE("/users/:id", handler.DeleteUser)
にて、下記の様なDELETE リクエストを受け取り、データを削除する。
curl -i -v -X DELETE "http://localhost:1324/users/1"
おわり
まあこんな所でしょうか。
あとは
- DBへの永続化
- エラーハンドリング
- デプロイ
当たりの優先順位でやっていきたい。
golang製Web Framework 「echo」事始め
はじめに
なんだか今日は早く目が覚めてしまったので、久しぶりの朝活。
golang
最近 golang が気になり過ぎているのと、Webアプリ作るフレームワークも出てきている様なので、Java、Scalaときて、第三の言語として扱えたらいいなーなんて思い、今年は真面目に勉強してみようかと。
実は前から既にちょくちょく書いていたのだけど、ちゃんとメモなりなんなりに残すのが大事なんだよね。
golang で書けるフレームワーク
フレームワークは僕が調べた中では、 martini というものが一番人気らしいのだけど、みんなが使っているものを勉強してもなーという天邪鬼な所があるので(Scalaの勉強を始めた時、周りの誰も使っていなかった)、 各フレームワークのベンチマーク を参考に、 echo というフレームワークを試すことにした。
なお、フレームワーク選びについては、下記Qiitaの記事を参考にさせていただいた。僕のブログ、というかこのエントリー含めてただのメモに比べると、こういう有益な記事には頭が上がらないっすね。
golang のインストール
いつも通りにbrew
$ brew install go
$GOPATH の設定
GOPATHが無いと色々不便(というか動かない?)みたい。
bashrcのPATHに、下記の様な感じで追加する。
export GOPATH=$HOME/.go export PATH=$PATH:$GOPATH
$ go version go version go1.7.5 darwin/amd64
echo の入手
go get
コマンドで入手
go get -u github.com/labstack/echo
入手すると、 $GOPATH
のディレクトリに格納される(ココらへんは go get
コマンドの話か)。
Helloworld
メモとか言っておきながら、やっぱり参考にする オフィシャルサイトのガイド そのまま。
HelloWorld
package main import ( "net/http" "github.com/labstack/echo" ) func main() { e := echo.New() e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) e.Logger.Fatal(e.Start(":1323")) }
起動
$ go run helloworld.go ⇛ http server started on [::]:1323
localhost:1323 にアクセスすると、 Hello, World!
と表示されるハズ。
echo のサンプルソース
下記に echo のサンプルソースが存在する。非常に参考になる。
~/.go/src/github.com/labstack/echo/cookbook
- auto-tls
- cors
- crud
- embed-resources
- file-upload
- google-app-engine
- graceful-shutdown
- hello-world
- http2
- jsonp
- jwt
- middleware
- streaming-response
- subdomains
- websocket
見た感じ、crudやらfile uploadやらtwitter oath認証やらなんでも揃っているので、組み合わせるだけでアプリが作れそうな勢いw
次回は、このcrudを参考にし、MVCモデルの様にアプリを構築出来るようにするための第1歩として
- router.go
- listUser.go
- createUser.go
- updateUser.go
- deleteUser.go
に分割してみる。
Supersetを試してみる
Supersetとは
宿泊施設マッチングサイトAirBnB(エアビーアンドビー)が提供する、データ可視化ツール
Supersetをインストールし、DBとつなぎ、Queryを書き、ヴィジュアライズしてダッシュボードを構築することで
マーケティングなどに役立てることが出来る
インストール方法
基本的にはオフィシャルサイトにある Superset’s documentation の通りにやっていけば良い
ここではMacOSにインストールする方法をメモっておく
Python の実行環境構築
SupersetはPython製なので、先ずはPython実行環境の構築
とは言っても、Homebrewで一発
$ brew install python
pkg-config、libffi、openssl をインストール
他に、pkg-config
、libffi
、openssl
等が必要となるそうなので、インストール
$ brew install pkg-config libffi openssl
pip について
pip
は、pythonのためのライブラリ管理ツール
homebrewやnodebrewみたいなもの
cryptography のインストール
Python製の暗号化ライブラリ
env LDFLAGS="-L$(brew --prefix openssl)/lib" CFLAGS="-I$(brew --prefix openssl)/include" pip install cryptography
env
については、 openssl
と cryptography
を結びつける設定かな?
あまり詳しくなくて申し訳無し
virtualenv
Pythonの仮想環境を構築できるパッケージ。
こちらも、 Superset’s documentation を参考にインストール
pip install virtualenv
こちらの記事がとても詳しく書かれていたので、参考に
superset のインストール
pip install superset
Adminユーザーを作成する
下記コマンドを実行すると、氏名、メルアド、パスワードを聞かれるので入力する
ここで入力した情報が初回ログインユーザーとなる
fabmanager
は、 Superset
がSQLiteにデータ登録するコマンド?
fabmanager create-admin --app superset
DBのイニシャライズを行う
これは、 Superset’s documentation に記載されたコトそのまま・・・
実際に何するかまでは調べていない
superset db upgrade
初期データを登録(多分スキップ可能)
これも、 Superset’s documentation に記載されたコトそのまま・・・
Supersetを利用する上で例となる、ものすごく豊富なデータを登録してくれる(スクリプトだと思っている)
superset load_examples
権限などの初期化
これも、 Superset’s documentation に記載されたコトそのまま・・・
superset init
サーバー起動
下記コマンドでSupersetを起動する
superset runserver
その後、 http://localhost:8088 にアクセスするとログイン画面が表示される
fabmanager
で登録したユーザーでログインできる
MySQLに接続する
SQLAlchemyについて
SQLAlchemyはPythonのためのO/Rマッパーとのこと
Python界(とSuperset)のことは何もしらないので間違っていたら申し訳ないのだけど
SupersetはこのORMを採用している
MySql Connector (PyMySQLのインストール)
SQLAlchemyとは別に、MySQLにつなげるConnectorが必要になる
僕が試したのは PyMySQL
。これが良いものかどうかはワカラナイけど、とりあえずこれでつなぐことが出きた。
PyMySQL
は pip
でインストールする。
pip install PyMySQL
MySql接続設定
上部の Sources
→ Databases
→ +ボタン
から、 SQLAlchemy URI
というフォームに
mysql+pymysql://{mysql_user}:{mysql_password}@localhost:3306/{database_name}
的なニュアンスでDB情報を入力
Test Connection
で確認。
最後に
最後に、とか書いてるけど、とりあえずセットアップぐらいまでの手順しかまとめられなかった。
ただ、 superset load_examples
をやってあげれば、それはもうエゲツないデータが登録され、グリグリしたなんかもう良くわからないグラフをダッシュボードから見ることが出来るので、是非お試しを。
エゲツないグラフは github のREADME.mdでgif確認出来るので、見てみると良い。
使い方はノリでできそう。
もう暫く触ってみたい。
シング・ストリート
傑作!
最近、娘ちゃんが寝た後に嫁ちゃんと映画をよく観るのだけど、せっかくだから面白い映画を観たいモノ。そして、実際ヒットが続いて嬉しい。
アイルランドに住む冴えない男の子が、好きになった女の子の気をひく為にバンドを組むお話。
家庭環境とか、学校での厳しい規則、いじめから現実逃避する為に、バンドを組んだ仲間と曲を書き、それが力になって行く様は観ていて気持ち良い。
初めはもう笑っちゃうくらい見た目がダサいのだけど、どの曲もとてもとても良い曲。
物語が進むにつれて次第に様になって行き、ラストに至っては「初めから最後までずっとかっこよかったんじゃないかな?」と錯覚するほど、めちゃくちゃカッコイイんだ。
主人公の兄ちゃんが、とにかく弟に何でも教えてあげる、またこれがいい男。役者が気になって調べたら、まだ日本語のウィキペディアが無いみたい。Jack Reynor - Wikipedia
登場人物全員が良い味出してる、傑作映画!
究極のダサカッコイイ。
スタートレック イン トゥー ザ ダークネス
なんだかハマりだした笑
観る前は全く興味なかったのだけど、観てみるとこれが意外に面白い。エイブラムスさんマジックかな?
そんで、前作よりもこのイントゥーザダークネスの方が面白かった!
何よりベネディクト・カンバーバッチが良すぎ。
新作のビヨンドも早く観たいな(プライム化して欲しいな…w