golangのお勉強9


## 構造体

* 構造体の初期化のパターンがあり、スタンダードな初期化は初期化関数がある
* 構造体に構造体をネストしたり、メソッドを追加したりする

急いで学ぶGo lang#5 構造体 ｜ Developers.IO
http://dev.classmethod.jp/server-side/language/golang-5/

	golangのオブジェクト志向、とてもわかりやすい。

## gormの事例

マイグレーションもgormでやってしまうと考えると

Go言語からGORMとECHOでJSONを返すAPIサーバー作ってみる。 - OngaLog
http://onga-tec.hatenadiary.jp/entry/2016/08/12/010938


## gooseパッケージ

`mattes/migrate`のdirtyフラグがしっくりこなかったのでgooseを使って見る。
is_appliedのフラグの命名が若干不思議。
downだとis_appliedがfalseで履歴が追加されるみたい。

設定方法の指定が若干わかりにくかったが環境変数からURI読み込みにする。

```dbconfig.yml
development:
    driver: postgres
    open: $POSTGRESQL_URI
```

内部では他パッケージのように`"github.com/lib/pq"`を使っているみたい。

Go製マイグレーションツールまとめ - Qiita
http://qiita.com/nownabe/items/1acce9f6b9f14f74c965#%E5%8F%82%E8%80%83

liamstask / goose — Bitbucket
https://bitbucket.org/liamstask/goose

goose/dbconf.go at master · letsencrypt/goose
https://github.com/letsencrypt/goose/blob/master/lib/goose/dbconf.go

## インタラクティブシェル

検証に使ったりした。
printが１回しかできない制限あり。
エラーで応答不能になったりもする気がする。
こういったものではなく、goplayをつかってもいいのではという記事もあった。

mkouhei/gosh: interactive shell for Golang
https://github.com/mkouhei/gosh

## pathパッケージ

`path.Base()`を使ってAPIのパスからidを切り出した。

path - The Go Programming Language
https://golang.org/pkg/path/

## Sirupsen/logrusパッケージ

パッケージのディレクトリが大文字になってしまう問題がありそう。
あとは、ちょうどいいformaterがあればいいな。
intellijでもフラグを立てればカラーリングを矯正できた

sirupsen/logrus: Structured, pluggable logging for Go.
https://github.com/Sirupsen/logrus

x-cray/logrus-prefixed-formatter: Logrus Prefixed Log Formatter
https://github.com/x-cray/logrus-prefixed-formatter

doloopwhile/logrusltsv: LTSV Formatter for Logrus
https://github.com/doloopwhile/logrusltsv

## op/go-loggingパッケージ

ひとまずこれを使って見るかな。。
カラーリングがintellijだと無効になってしまう。

op/go-logging: Golang logging library
https://github.com/op/go-logging


## エラーハンドリング

エラーをどうするのがいいのか。。
Error,panic,os.Exit,returnなどありそう。。

ひとまずは下記のイメージにしておく。

* プログラム処理の致命的なエラー
	* panic/recover
* 例外処理的なエラー
	* return/defer
* 想定されるエラー
	* Error構造体
* deferを無視したい場合
	* os.Exit()

エラー・ハンドリングについて（追記あり） — プログラミング言語 Go | text.Baldanders.info
http://text.baldanders.info/golang/error-handling/

	returnして必要ならdefer。

## ファイル構成

	シンプルな形

Go言語からGORMとECHOでJSONを返すAPIサーバー作ってみる。 - OngaLog
http://onga-tec.hatenadiary.jp/entry/2016/08/12/010938

## encoding/jsonパッケージ

詳しい、、まだ理解してない。

Friday the 13th - Gopher vs JSON!! - Qiita
http://qiita.com/hogedigo/items/f914992baf7a2ed12b9c

Marshalしたのと同じ構造体なのにUnmarshalできないと思って四苦八苦した。

Goのjson.Marshal/Unmarshalの仕様を整理してみる · I Will Survive
http://blog.restartr.com/2014/08/13/golang-json-marshal-unmarshal/

> goの構造体につけるタグは、フォーマットが不正だと読み込まれない(当然)
json.Marshalは、構造体のjsonタグがあればその値をキーとしてJSON文字列を生成する
json.Unmarshalは、構造体のjsonタグがあればその値を対応するフィールドにマッピングする
jsonタグがなければ、完全一致もしくはcase-insensitiveなフィールドにマッピングする

結局、new()を使うとStructタグがコピーされない（アノーテーション）ために、復元ができなかったらしい。
Swaggerが生成してくれたコードだったのだがそのままつかえればよかったのに。。
（json文字には小文字を使うのが多分よい。構造体のスコープの指定が頭文字の大文字小文字。）

```
type InlineResponse200 struct {
	Name string `json:"name"`
	Contents string `json:"contents"`
}

okString := "[{\"Name\":\"なまえだよ\",\"Contents\":\"こんてんつだよ\"}]"
fmt.Fprintln(w, okString)

//元に戻すチェック
var successPayload = new([]swagger.InlineResponse200)
err = json.Unmarshal([]byte(okString), &successPayload)
applog.Info(err)
applog.Info(successPayload)

//元に戻すチェック(小文字で復元してくれた)
okString = "{\"name\":\"なまえだよ\",\"contents\":\"こんてんつだよ\"}"
var successPayload2 swagger.InlineResponse200
err = json.Unmarshal([]byte(okString), &successPayload2)
applog.Info(err)
applog.Info(successPayload2)

//元に戻すチェック
okString = "[{\"Name\":\"なまえだよ\",\"Contents\":\"こんてんつだよ\"}]"
var successPayload3 []swagger.InlineResponse200
err = json.Unmarshal([]byte(okString), &successPayload3)
applog.Info(err)
applog.Info(successPayload3)

//元に戻すチェック
okString = "[{\"Name\":\"なまえだよ\",\"Contents\":\"こんてんつだよ\"}]"
var successPayload4 = make([]swagger.InlineResponse200, 2)
err = json.Unmarshal([]byte(okString), &successPayload4)
applog.Info(err)
applog.Info(successPayload4)

```

使い分けがわからない。。
そもそも、newとかmakeとかわかってない。。

どうやら、encoding/jsonの内部ではreflectパッケージが使われてstructタグの情報を取得している。

Struct タグについて — プログラミング言語 Go | text.Baldanders.info
http://text.baldanders.info/golang/struct-tag/

## go-swaggerとswagger codegen

swagger codegenで生成したコードをいじっているがいろいろ見つかって困りつつ勉強になる。

go-swaggerというパッケージでも生成ができてこちらのほうが完成度は高いらしい。
ただ、調整しづらい部分もいくつかあったのかな？？いまさらだけど。

Goa: Design-First API Generation | Hacker News
https://news.ycombinator.com/item?id=12004218

> Overall the default swagger codegen is very simplistic and the alternative go-swagger code is better but has a few rough edges that are difficult to fix.

下記のイメージ。

go-swagger: より良いが癖がある
swagger codegen: 最低限のサンプルレベルだがシンプル

codegenをカスタマイズする方法もあるらしい。。へー。。Groovyかあ。

こんなに簡単! Swagger Codegenのカスタマイズ - Qiita
http://qiita.com/Quramy/items/c583f3213f0b77ff1bac

> そうです、こんなときこそGroovyの出番です。

swagger-codegen/modules/swagger-codegen/src/main/resources at master · swagger-api/swagger-codegen
https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources

## goa

うーん、やってみようかなあ。。
コードが綺麗なら乗り換えた方が効率的かも。。
まだロジックの実装はほとんど進んでないし。。

これからMicroservicesな開発をするならgoaがおすすめという話 - Qiita
http://qiita.com/y_matsuwitter/items/1298adfcd26c84f7d20b#_reference-f9e0db65923c64c50061

goa でデザイン・ファーストをシュッとする - Qiita
http://qiita.com/ikawaha/items/6638ee8b6978aef50d65#_reference-1585e09173db4b55de96

お、定義から生成できるのすごい。

Swagger 定義から goa の design を生成する ago という CLI を作りはじめた - tchsskのブログ
http://tchssk.hatenablog.com/entry/2016/12/17/211443