Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Go言語で色々試行錯誤して フレームワークもどきを作ってみた話

802 views

Published on

LTLovers 4th - My neutral fat is high -での登壇資料になります。
https://ltlovers.connpass.com/event/90485/

Go言語を学びはじめて、その過程のなかでAPI構築用のフレームワークもどきを作成した過程で得た気づきや知見等についてざっくりとまとめたものになります。
また、この中で紹介しているリポジトリについても鋭意開発は継続していく所存です。

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Go言語で色々試行錯誤して フレームワークもどきを作ってみた話

  1. 1. Go言語で色々試行錯誤して フレームワークもどきを作ってみた話 LT Lovers 4th @ アイスタイル様 2018 / 06 / 26 Fumiya Sakai
  2. 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に該当。 何卒お手柔らかによろしくお願いします😓
  3. 3. このトピックスを選んだ理由 以前に一度触ってみようと思ってほったらかしていたGo言語に思い切って挑戦 当初に抱いていた勝手なイメージ: ・�文法が今まで扱ってきた言語と勝手が思いっきり違いそう ・�ClassやGenericsがないから面倒くさそう ・�でも慣れるとAPIとかバッチ処理はシンプルに書けそう Server Side (Ruby & PHP) Client Side (Swift & ReactNative) そうは言うてもやってみないと何も始まらんやん! 初めはGo言語自体に恐れを感じていた と同時にGo言語自体に憧れを感じていた ・�自分のエンジニア友達の界隈でもよく聞くから楽しそう
  4. 4. まずは基本からしっかりとやってみる 一旦はさらっと流して全部読む まずは何と言ってもA Tour of Goを眺める + 既存の教材からスタートしてみる 充実してるがゴツい… ・ 章立てはしっかりしているが必要そうなところ だけをうまくかいつまんで進める ・ 基本的な文法の理解は書いていく上でのいち ばん大切な部分なのでしっかりと進める
  5. 5. ただやっぱり基本だけでは何か物足りない そうだ、アプリのサーバーサイドのAPI部分を実装してみようと思い立つ 一番最初の設計方針 ぶつかった壁と問題 これまで嗜んだもの一覧 ・�Go言語 + MVCパターンでCRUDができるAPIをつくる方針 ・�便利なパッケージはなるべく使って試しながら進めていく 初めは触りなれたMVCパターンに当てはめてみては? ・�ModelとControllerに分類しにくい機能はどうしよう… ・�Structの整理をどうしよう… 強引にそれっぽくしてみたものの個人的にものすごい違和感 ・ CakePHP / CodeIngiter / Laravel / Symfony PHP ・ Ruby on Rails / Sinatra Ruby ・ そもそもiOSのアーキテクチャはMVCパターン iOS (Swift) 悪い意味で囚われ過ぎてしまったか…?
  6. 6. CRUD操作のDEMOを行います サンプルリポジトリ ・Githubサンプル (まだまだ機能追加の試行錯誤中です…) https://github.com/fumiyasac/SampleApiOfGo コンソール経由での操作デモを行います そうだ、アプリのサーバーサイドのAPI部分を実装してみようと思い立つ
  7. 7. 今回のサンプルで導入したパッケージの一覧 パッケージ名 パッケージの機能概要 dep  パッケージの依存関係の管理をするために用いる goose MySQLをはじめとするデータベースのスキーマ定義を管理するために用いる swag GodocからSwaggerによるAPI定義書の書き出しをするために用いる gin-swagger(/swaggerFiles) Ginを利用した構成の際に上記の処理ができるようにするために用いる パッケージ名 パッケージの機能概要 Gin ルーティング(APIのエンドポイント)に関する設定をする際に用いる xorm MySQLをはじめとするデータベースのデータ操作用のORMapper bcrypt パスワード等をハッシュ化する際に用いる まだ機能がほとんどないので諸々の検証も含めて試しています アプリケーションの構築に関するパッケージ 便利ツール&運用保守に関するパッケージ
  8. 8. 基本的な概要設計 下記のような構成でざっくりと役割ごとに分けて考えてみる main.go Interface controller ・ Routing / EndPoint repository validator factory MySQLentity constants middleware database アプリケーションのサポートに関する部分 mapping アプリケーションのロジック部分 リクエスト処理部分&ロジック部分 ・ Business Logic / API Response
  9. 9. 今回のサンプルでの階層構造の概要 パッケージ名 パッケージの機能概要 constants どこでも使うような定数値やenumのような形で使いたいものを格納する。 controllers エンドポイントからのリクエスト/レスポンスに関わるものを格納する。 database 接続するデータベース(ORMの接続設定やMigraion関連)に関わるものを格納する。 entities 接続しているテーブルのDBスキーマ定義と構造体を格納する。 factories APIレスポンス形式の雛形となる構造体を格納する。 middleware [機能作成中...]全体もしくは一部の処理で共通して必要な前後処理を割り込ませる。 repositories APIレスポンスを構築するためのロジックに関わるものを格納する。 static HTMLやCSS等の静的ファイルに関わるものを格納する。 作成中...]全体もしくは一部の処理で共通して必要な前後処理を割り込ませる。続する validators APIレスポンスを構築するためのロジックに関わるものを格納する。 main.go 主にここではエンドポイントの管理を担当している。 作成中...]全体もしくは一部の処理で共通して必要な前後処理を割り込ませる。続する まだ機能がほとんどないので諸々の検証も含めて試しています アプリケーションの実行に関するものの一覧
  10. 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. 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のカラム名
  12. 12. 運用・これからの管理にも役立ちそうなパッケージを探す 他のフレームワークでも利用しているような便利なツールの活用と検証 他のFWでもあるもの ・�DatabaseのマイグレーションとDB構造の管理 ・�利用しているパッケージ(ライブラリ)と依存性の管理 平素のRailsやiOS開発でも活用しているものの代表的な例 ・(参考) SwaggerでRESTful APIの管理を楽にする https://qiita.com/disc99/items/37228f5d687ad2969aa2 ※ ここではSwaggerのボトムアップ形式の開発 Swaggerを試してみる Goose (Database migration) dep (Package dependencies) Controllers/Factories等のファイルに GoDoc形式で記載されたコメント ・ goファイルのコメントからAPI定義書の作成 ・ SwaggerUIドキュメントの閲覧や更新が容易
  13. 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. 14. まとめ なんだかんだで親しみやすかった&パッケージの充実ぶりがありがたかった 1. 複数のパッケージをうまく組み合わせる & シンプルな感じが個人的に好きになった 2. 実装だけではなく運用や管理ツールに関するパッケージ ・とりあえずすぐに動かして試すところまでが、パッケージを組み合わせるだけ実現できた ・Structの扱いや文法の部分はこれまで親しんできた言語とは勝手が違うので、この部分は最初ものすごいハマった ・これまで親しんできたフレームワークで導入してきたライブラリやツールに近いものもあった ・特にコード内のGoDocを元にSwaggerでのAPI定義書の書き出しができるライブラリがエエ感じで驚きました! 今回の登壇内で紹介したサンプルに関しましては、今後も鋭意開発&運用を続けていく所存です😅 😅 😅 ・文法は少し今まで親しんできた言語とは異なるもの、慣れればシンプルで結構書きやすく感じた

×