martiniからnegroniが生まれた背景とリフレクション
弊社ではGoのWebフレームワークの中でnegroniを採用している。
negroni
net/httpと直接結びついて動作する、ミドルウェアにフォーカスされたライブラリ。
セッション管理したりユーザ認証の際に利用されることが多い。
negorniでは `gin`というコマンドを使う。
ginコマンドではソースコードをビルドしてバイナリをたちあげる作業を行う。
negroniは変更をlistenしているのでソースコードを変更して保存したタイミングで更新してくれるために開発で便利。
negroniの誕生背景
negroniの作者はnegroniを作る前にmartiniというライブラリを作っていた。
martiniはリフレクションを良く使うライブラリで、そのためにGoにしては処理が遅いが、裏でよろしくやってくれて便利だった。
これはauto magicと称された。
しかし、Goの文化的に利用する側が何が行われているのか把握できないブラックボックスはよくないという批判があった。
これをうけ、作者が新しく作ったのがnegroni。
フレームワークを比較している記事
Go Web Frameworks 比較qiita.com
型
型には名前を持つ型と名前を持たない型がある。
名前を持つ型
type Team struct
名前を持たない型
`[]byte` や `*int` など型の名前と記号によって表される。
map[string]string interface{}
複数の型をうけいれる型
型には複数の型を受け入れるインターフェース型がある。
fmt.Prinflnが例として挙げられる。
func Println(a ...interface{})(n int, err error)
型の中でも静的な型と動的な型があるが、インターフェース型はどちらも受け入れることができる。
var n int = 42 // nの(静的な)型はint var s string = "hello" // sの(静的な)型はstring var v interface{} // vの(静的な)型はinterface{} v = n // vの(静的な)型はinterface{}、動的な型はint v = s // vの(静的な)型はinterface{}、動的な型はstring
reflect機能
reflectパッケージを使用すると変数の型についての情報を取得することができる。
package main import ( "fmt" "reflect" ) func main() { type MyInt int var x MyInt v := reflect.ValueOf(x) // ValueOfでreflect.Value型のオブジェクトを取得 fmt.Println(v.Type()) // Typeで変数の型を取得 fmt.Println(v.Kind()) // Kindで変数に格納されている値の種類を取得 } // main.MyInt // int
インターフェース型の場合は動的な型の情報も取得することができる。
値を格納していない場合にはメソッドがpanicを起こすので値が格納されているか否かはIsValidメソッドでチェックする。
func HasField(v interface{}, name string) bool { rv := reflect.ValueOf(v) // ポインタ型であるか if rv.Kind() == reflect.Ptr { // ポインタの要素の型を返す rv = rv.Elem() } // 構造体であるか if rv.Kind() != reflect.Struct { return false } // 引数に渡された項目がオブジェクトの項目に値があるか判定して返す return rv.FieldByName(name).IsValid() }
reflectについて詳しいサイト
reflect パッケージ - golang.jp