LoginSignup
3

More than 5 years have passed since last update.

golangのお勉強9

Last updated at Posted at 2017-07-01

構造体

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

急いで学ぶ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が1回しかできない制限あり。
エラーで応答不能になったりもする気がする。
こういったものではなく、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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3