Go言語でAPI作った話
書くこと
Go言語でRestAPIつくりましたって話
参考にした本とか記事とか
環境構築とか
書いたソースと簡単な説明とか
その他感想とか
Go言語でRestAPI作りましたって話
RestAPIって言っても、ランダムに運勢をJSON形式で返すだけの おみくじAPIです。 GETメソッドで omikuji.json を叩くと運勢が帰ってきます。 ブラウザで直接開いた場合以下のような感じです。まんまJSONです。
参考にした本とか記事とか
まず一通り基本的な文法とか、お作法的なところを↓の本で勉強しました。 ちなみに今回はKindle版を買った。検索は対応してるっぽいです。
https://www.amazon.co.jp/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0Go%E8%A8%80%E8%AA%9E-%E6%9D%BE%E5%B0%BE%E6%84%9B%E8%B3%80-ebook/dp/B01FH3KRTI?ie=UTF8&qid=&ref_=tmm_kin_swatch_0&sr=www.amazon.co.jp
で、RestAPI作りたいなーって思ったら以下の記事を見つけたので参考にさせていただきました。
環境構築とか
上の記事で使用されている go-json-rest なるライブラリを使いましょうという方針でいく。 が、俺の環境にはまだそんなライブラリを落としてきていない。ので落としてくるのだが、じゃあどうやるのかというと、 俺は↓の記事を参考に ghq なる物をインストールし、ghqを使用して go-json-rest をインストールしました。
書いたソースと簡単な説明とか
構成
パッケージ構成は以下のようにしました。 ソース内の packaege ~~~ も実際のフォルダ構成と同じ。
main ├ bin/ └ main/ ├ OmikujiApi.go │ ├ data/ │ └ OmikujiData.go │ └ resource └ Omikuji.go
OmikujiApi.go
なんかいろいろやってる。 go-json-rest ライブラリのAPIをちゃんと読まないといけないんだけど、 たぶん、 * 受け付けるメソッドの設定(GETとかPOSTとかDELETEとか)、 * パスのルーティング(? っていう言葉でいいのかな) http:// ... /omikuji.json というパスとそのパスにアクセスされた場合に実行する処理の紐付け * 何番のポートを使うかの設定 (今回は 8081番)
をやっている。(つもりになってます。)
package main import ( "net/http" "github.com/ant0ine/go-json-rest/rest" "./resource" "log" ) func main() { api := rest.NewApi() api.Use(rest.DefaultDevStack...) api.Use(&rest.CorsMiddleware{ RejectNonCorsRequests: false, OriginValidator: func(origin string, request *rest.Request) bool { return true }, AllowedMethods: []string{"GET"}, AllowedHeaders: []string{ "Accept", "Content-Type", "X-Custom-Header", "Origin"}, AccessControlAllowCredentials: true, AccessControlMaxAge: 3600, }) router, err := rest.MakeRouter( rest.Get("/omikuji.json", resource.GetOmikuji), ) if err != nil { log.Fatal(err) } api.SetApp(router) log.Fatal(http.ListenAndServe(":8081", api.MakeHandler())) }
OmikujiData.go これが実際にJSON形式にして返すデータ。 SetUnsei() を使うと運勢がランダムにセットされる。
package data import ( "time" "math/rand" ) type OmikujiData struct { Unsei string } func (omikujiData *OmikujiData) SetUnsei() { unseiMap := map[int]string{ 0: "大吉", 1: "中吉", 2: "小吉", 3: "末吉", 4: "吉", 5: "凶", 6: "末凶", 7: "小凶", 8: "中凶", 9: "大凶", } rand.Seed(time.Now().UnixNano()) unsei := unseiMap[rand.Intn(10)] omikujiData.Unsei = unsei }
Omikuji.go
OmikujiData構造体をJSONにして返す関数を書いた。
package resource import ( "github.com/ant0ine/go-json-rest/rest" "../data" ) func GetOmikuji(w rest.ResponseWriter, r *rest.Request) { omikujiData := new (data.OmikujiData) omikujiData.SetUnsei() w.WriteJson(omikujiData) }
その他感想とか
正直、ここまでめっちゃスムーズにできたと思う。 JavaでJAX-RSのプロジェクト作って、RestAPIの動作確認まで…とかと比べてだけど。 たぶん Go言語の方がずっと詰まるところが少なかったと思う。
動作が確認できるまでの途中途中での、「なんかうまくいかないんだが?」っていうのってモチベーションの維持に非常に関わるので、 そういうのが少ないのって素晴らしいと思う。まる。
webpack + Babel + React(ES2015使用)の設定
やりたいこと。 * ReactをJSXを使用して書きたい。 * EcmaScriptの構文も使用して書きたい * .jsファイルと、.jsxファイルに変更があった場合自動的にビルドしてほしい。 * 自動的にソースマップも出力してほしい。
webpack.config.js
// コマンドメモ // -p : minify // --watch : ファイルの変更を監視 ビルドの自動化 // $ webpack -p --progress --colors --watch var path = require('path'); var webpack = require('webpack'); module.exports = { // エントリーポイント entry: './script/src/main.jsx', // ソースマップ出力 devtool: "#source-map", // 出力先設定 output: { path: __dirname, filename: './script/dest/bundle.js' }, module: { loaders: [ // .jsxファイル用 { test: /.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, query: { presets: ['es2015', 'react'] } }, // .jsファイル用 { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/, query: { presets: ['es2015'] } } ] }, resolve: { // ここに登録した拡張子は import時に省略できる extensions: ['', '.js', '.jsx'] } };
以下のコマンドで実行
$ webpack -p --progress --colors --watch
俺がBracketsに入れてるエクステンションまとめ
Mac でも Windows でも使えて、動作が安定していて、標準で日本語に対応していてライブプレビューできて簡易サーバー立ち上げられる最強伝説エディタ Bracketsに俺がよく追加しているエクステンションまとめた。
相変わらずUTF-8のファイルしか扱えないけど、そこは割り切っていこう。
React (.jsx) language mode for Brackets
React(.jsx)モードを追加するエクステンション
Go-IDE
Go言語モードを追加するエクステンション
Monokai Dark Soda
テーマを変更するやつ。 黒ベースで最高にCoolだぜ。
FuncDocr
JSDocのテンプレートを挿入してくれるやつ。 ためしてないけどPHPでもいけるっぽい。
Tabs - Custom Working
開いてるファイルをタブ表示してくれるやつ。
Show Whitespace
スペースとかタブとかを可視化してくれるやつ。 可視化されてないと不安になるので、精神衛生上とても重要なエクステンション。
Indent Guides
インデントにあわせて縦線を表示してくれるやつ。 上の Show Whitespace とのコンボで最強になれる。
Brackets Exclude Indexing FileTree
開いているフォルダー内に 30000以上ファイルがあるとエラーになるんだが、node_moduleフォルダとかあると簡単に30000ファイルくらい超えるので、node_moduleを編集対象のフォルダから除外してくれるエクステンション。
上にあげたエクステンションのみ有効にした場合こんな感じになる。
もっとゴテゴテにカスタマイズしてた時もあったけど、今はシンプルに保つのもいいかなと思ったりしているところ。
「UXデザイン入門」読みました
↑の「UXデザイン入門」を読んだ。
というのも、UIを作る技術があっても、UIといっしょに語られることが多いUXについてほとんど勉強したことがなかったので。
本の内容としては、UXを設計する過程で行うべきアンケートとかインタビューとかの方法が詳しく解説されていた。
一方で「UXデザイン入門」と言っているだけあり、どういう場合にどういうコンポーネントを使うと効果的とかいう話はほとんどなかった。そもそも、そういう定石みたいなものなんて無いのか。
面白いなーって思ったのは、設計する上で、そのアプリケーションを使用想定するターゲット(ペルソナ)を詳細に(名前や趣味まで)設定すべきっていうところで、はぁーなるほどぉってなった。
まる。
React + gulp サンプル
Material Design Lite
React
React使いつつ、マテリアルデザインも使いたいなーと思って、Material Design Lite を組み合わせてみた時のメモ。
ビルドツールには gulp を使用したので、まず gulpfile.js から。
var gulp = require('gulp'); var uglify = require('gulp-uglify'); var plumber = require('gulp-plumber'); var browserify = require('browserify'); var source = require("vinyl-source-stream"); var reactify = require('reactify'); var buffer = require('vinyl-buffer'); gulp.task('dist', function(){ var bundler = browserify('./script/src/main.jsx', { debug: true }); return bundler .transform(reactify) .bundle() .pipe(plumber()) .pipe(source('build.js')) .pipe(buffer()) .pipe(uglify()) .pipe(gulp.dest('./script/dist/')); }); gulp.task('watch', function() { gulp.watch('./script/src/*.js', ['dist']); gulp.watch('./script/src/*.jsx', ['dist']); gulp.watch('./script/src/**/*.js', ['dist']); gulp.watch('./script/src/**/*.jsx', ['dist']); }); gulp.task('default', ['dist', 'watch']);
次に HTMLファイル。 body要素の最後で、ビルド後のjsファイルを読み込むようにする。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>test</title> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="./style/material.min.css" rel="stylesheet"> <link href="./style/style.css" rel="stylesheet"> </head> <body> <noscript>JavaScriptを有効にして下さい。</noscript> <div id="appView"></div> <script src="./script/dist/build.js"></script> </body> </html>
エントリーポイントとなる main.jsx 3行目で、Material Design LiteのJavaScriptを読み込んでいる。 6行目で読み込んでいる AppView.jsx がルートコンポーネント。
(function () { 'use strict'; var mdl = require('material-design-lite'); var React = require('react'); var ReactDOM = require('react-dom'); var AppView = require('./component/AppView.jsx'); // アプリケーション全体のコンポーネントを表示 ReactDOM.render( <AppView />, document.getElementById('appView') ); }());
Go言語インストールからHelloWorld、あと特徴とか忘れないうちにメモっとく
インストール手順
MacにHomebrewを使ってインストールした。Homebrewはインストール済の前提。
$ brew install go
バージョンを確認
$ go version
Hello World!
package main import ( "fmt" ) func main() { fmt.Println("Hello World!") }
Hello World 実行手順
自分は以下のような sh ファイルを作った。
今回はとりあえず test.sh という名前で保存した。
export GOPATH=任意のパス export PATH=$PATH:$GOPATH/bin cd ${GOPATH} go install ./src/github.com/jsuzuki20120311/go_test
Hello Worldのソースが書けたら、
$ ./test.sh
その後、別窓でターミナルを開いて
$ ./go_test Hello World!
Hello World! が出力されればめでたしめでたし。
その他、Hello Worldやる過程で調べてわかったこととかメモ
クラスなんてものは無い 代わりに 構造体 なるものがある
実際に書いてみた。
type box struct { width int } func (b *box) get_width() int { return b.width } func main() { b := box{width: 10} fmt.Println(b.get_width()) }
他、継承なんてない。コンポジッション関係を使え。あとインタフェースはある。 このあたりを箇条書きにすると
- is - a 関係 : × 代わりに has - a 使え
- has - a 関係 : ○
- can do 関係 : ○
また別の日にもう少し詳しく整理して書こうと思う。