More Related Content Similar to Go言語で色々試行錯誤して フレームワークもどきを作ってみた話 (20) More from Fumiya Sakai (14) Go言語で色々試行錯誤して フレームワークもどきを作ってみた話2. 自己紹介
・酒井 文也 (Fumiya Sakai)
・Designer → ServerSide Engineer → AppDeveloper
Accounts
・Facebook: https://www.facebook.com/fumiya.sakai.37
・Twitter: https://twitter.com/fumiyasac
・Github: https://github.com/fumiyasac
・Qiita: https://qiita.com/fumiyasac@github
Who are you?
Library (Personal)
【本職: Swiftを書いているiOSエンジニアです】
Golang歴は浅い(1ヶ月)です
仕事でやっていること :
・ メディカル/ヘルスケア系の新規アプリの開発
や保守全般(2本)
・ iOSアプリに関わるお仕事全般の担当&ポジショ
ンはサッカーで例えるならDFに該当。
何卒お手柔らかによろしくお願いします😓
7. 今回のサンプルで導入したパッケージの一覧
パッケージ名 パッケージの機能概要
dep パッケージの依存関係の管理をするために用いる
goose MySQLをはじめとするデータベースのスキーマ定義を管理するために用いる
swag
GodocからSwaggerによるAPI定義書の書き出しをするために用いる
gin-swagger(/swaggerFiles) Ginを利用した構成の際に上記の処理ができるようにするために用いる
パッケージ名 パッケージの機能概要
Gin ルーティング(APIのエンドポイント)に関する設定をする際に用いる
xorm MySQLをはじめとするデータベースのデータ操作用のORMapper
bcrypt パスワード等をハッシュ化する際に用いる
まだ機能がほとんどないので諸々の検証も含めて試しています
アプリケーションの構築に関するパッケージ
便利ツール&運用保守に関するパッケージ
9. 今回のサンプルでの階層構造の概要
パッケージ名 パッケージの機能概要
constants どこでも使うような定数値やenumのような形で使いたいものを格納する。
controllers エンドポイントからのリクエスト/レスポンスに関わるものを格納する。
database 接続するデータベース(ORMの接続設定やMigraion関連)に関わるものを格納する。
entities 接続しているテーブルのDBスキーマ定義と構造体を格納する。
factories APIレスポンス形式の雛形となる構造体を格納する。
middleware [機能作成中...]全体もしくは一部の処理で共通して必要な前後処理を割り込ませる。
repositories APIレスポンスを構築するためのロジックに関わるものを格納する。
static HTMLやCSS等の静的ファイルに関わるものを格納する。
作成中...]全体もしくは一部の処理で共通して必要な前後処理を割り込ませる。続する
validators APIレスポンスを構築するためのロジックに関わるものを格納する。
main.go 主にここではエンドポイントの管理を担当している。
作成中...]全体もしくは一部の処理で共通して必要な前後処理を割り込ませる。続する
まだ機能がほとんどないので諸々の検証も含めて試しています
アプリケーションの実行に関するものの一覧
10. 実装部分のコード例(1)
Controller部分ではJSONを作成する形にし、具体的な処理や整形はRepositoryに集約
func (ctrl UserController) GetUsers(c *gin.Context) {
userRepository := repositories.NewUserRepository()
userData, fetchResult := userRepository.GetLists()
if fetchResult != true {
errorMessage := factories.APIErrorMessageFactory{
Message: constants.ErrorMessageOfUserNotFound,
}
c.JSON(http.StatusBadRequest, errorMessage)
return
}
c.JSON(http.StatusOK, userData)
}
Controller〜Repository側の処理例: 登録ユーザーの一覧を表示する
// UserRepository ... interfaceの宣言
type UserRepository interface {
GetLists(id int) (factories.SingleUserFactory, bool)
…
}
・ リクエストをいい具合に加工してレスポンスを返却
controller
// GetLists ... ユーザー一覧情報を取得する
// @GET("api/v1/users")
func (repo UserRepository) GetLists()
(factories.UserItemsFactory, bool) {
… MySQLからユーザーの一覧情報を取得する
return userItemsFactory, true
}
repository
controller
ControllerのActionをシンプルに
11. 実装部分のコード例(2)
Factory部分でレスポンス時の表示内容を定義し、DB操作はEntityで行う
// GetByID ... 引数のidに該当するユーザー情報を取得する
// @GET("api/v1/users/:id")
func (repo UserRepository) GetByID(id int) (factories.SingleUserFactory, bool) {
var user = entities.User{}
var userFactory factories.SingleUserFactory
result, _ := engine.Where("id = ?", id).Get(&user)
if result {
userFactory = factories.SingleUserFactory{
ID: user.ID,
Username: user.Username,
MailAddress: user.MailAddress,
Password: user.Password,
UserStatus: “登録済",
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}…
// User ... 登録されているユーザー情報用の構造体
type User struct {
ID int `xorm:"'id'"`
Username string `xorm:"'username'"`
MailAddress string `xorm:"'mailaddress'"`
Password string `xorm:"'password'"`
StatusCode int `xorm:"'status_code'"`
CreatedAt time.Time `xorm:"'created_at'"`
UpdatedAt time.Time `xorm:"'updated_at'"`
}
entity
factory
repository
Username string `json:"username" example:"samplename"`
型とサンプル値をまとめたStruct
Tableのカラム名
13. Gin + swagを利用したSwaggerでのAPI定義書作成
// GetUsers godoc
// @Summary ユーザー一覧を表示する
// @Description userテーブルに登録されているデータを全件取得する
// @Accept json
// @Produce json
// @Success 200 {object} factories.UserItemsFactory
// @Failure 400 {object} factories.APIErrorMessageFactory
// @Router /users [get]
// SingleUserFactory ... JSONにマッピングする構造体の宣言
type SingleUserFactory struct {
ID int `json:"id" example:"1"`
Username string `json:"username" example:"samplename"`
MailAddress string `json:"mailaddress" example:"sample@example.com"`
Password string `json:"password" example:"(crypted strings...)"`
UserStatus string `json:"status" example:"有効"`
CreatedAt time.Time `json:"created_at" example:"2018-05-15T12:59:09+09:00"`
UpdatedAt time.Time `json:"updated_at" example:"2018-05-15T12:59:09+09:00"`
}
EndPointのRequest/Response等
Factoryに「example: “サンプル値”」と定義する
ことで各エンドポイントでのパラメーター欄やデー
タの構造部分の凡例を表示できるので便利です!
取りうる値の例やデータ定義
レスポンスのjson構成の部分をFactoryに切
り出す構造にすることで扱いやすくすると同時
にSwaggerとの連携もしやすくする。
14. まとめ
なんだかんだで親しみやすかった&パッケージの充実ぶりがありがたかった
1. 複数のパッケージをうまく組み合わせる & シンプルな感じが個人的に好きになった
2. 実装だけではなく運用や管理ツールに関するパッケージ
・とりあえずすぐに動かして試すところまでが、パッケージを組み合わせるだけ実現できた
・Structの扱いや文法の部分はこれまで親しんできた言語とは勝手が違うので、この部分は最初ものすごいハマった
・これまで親しんできたフレームワークで導入してきたライブラリやツールに近いものもあった
・特にコード内のGoDocを元にSwaggerでのAPI定義書の書き出しができるライブラリがエエ感じで驚きました!
今回の登壇内で紹介したサンプルに関しましては、今後も鋭意開発&運用を続けていく所存です😅 😅 😅
・文法は少し今まで親しんできた言語とは異なるもの、慣れればシンプルで結構書きやすく感じた