Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go言語でAPIサーバーを実装しました
Search
yoskeoka
February 24, 2018
Technology
7
2.7k
Go言語でAPIサーバーを実装しました
GoでCtoCサービスのAPIサーバーを実装した構成
今回の構成で良かったところ
困ったところ、直したいところ
yoskeoka
February 24, 2018
Tweet
Share
More Decks by yoskeoka
See All by yoskeoka
フロントエンドの変遷がもたらしたバックエンドの進化
yoskeokamoto
3
770
Other Decks in Technology
See All in Technology
Firestore → Spanner 移行 を成功させた段階的移行プロセス
athug
1
490
大「個人開発サービス」時代に僕たちはどう生きるか
sotarok
20
10k
新アイテムをどう使っていくか?みんなであーだこーだ言ってみよう / 20250911-rpi-jam-tokyo
akkiesoft
0
290
Rustから学ぶ 非同期処理の仕組み
skanehira
1
140
【初心者向け】ローカルLLMの色々な動かし方まとめ
aratako
7
3.5k
roppongirb_20250911
igaiga
1
240
LLMを搭載したプロダクトの品質保証の模索と学び
qa
0
1.1k
ブロックテーマ時代における、テーマの CSS について考える Toro_Unit / 2025.09.13 @ Shinshu WordPress Meetup
torounit
0
130
「全員プロダクトマネージャー」を実現する、Cursorによる仕様検討の自動運転
applism118
22
11k
生成AI時代のデータ基盤設計〜ペースレイヤリングで実現する高速開発と持続性〜 / Levtech Meetup_Session_2
sansan_randd
1
150
要件定義・デザインフェーズでもAIを活用して、コミュニケーションの密度を高める
kazukihayase
0
120
Terraformで構築する セルフサービス型データプラットフォーム / terraform-self-service-data-platform
pei0804
1
180
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Visualization
eitanlees
148
16k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
Site-Speed That Sticks
csswizardry
10
820
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
A Modern Web Designer's Workflow
chriscoyier
696
190k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.4k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.9k
Into the Great Unknown - MozCon
thekraken
40
2k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Transcript
Go言語でAPIサーバーを実装しました 2018.02.24 Umeda.go #3 1 Gemcook エンジニア 岡本 洋輔
ࣗݾհ ໊લɹ ॴଐ 2 BEFORE AFTER Ԭຊ༸ี PLBNPUPZPTVLF HDPLB (JUIVC
HDPLB RJJUB લ͔Βגࣜձࣾ(FNDPPL %PDLFS (PMBOH୲ ༻ٕज़
ࠓ͢͜ͱ (PͰ$UP$αʔϏεͷ"1*αʔόʔΛ࣮ͨ͠ߏ ࠓճͷߏͰྑ͔ͬͨͱ͜Ζ ࠔͬͨͱ͜Ζɺ͍ͨ͠ͱ͜Ζ 3
αʔϏεͷߏ 4 Ϣʔβʔཧ ϑϩϯτΞϓϦ ܾࡁαʔϏε APIαʔόʔ σʔλϕʔε
APIαʔόʔʹ͍ͬͯΔύοέʔδ 8"' 8FC"QQMJDBUJPO'SBNFXPSL w(JO 03Ϛούʔ w9PSN 5
WAF (Web Application Framework) w 3&45"1*αʔόʔΛ࡞ΔͷͰγϯϓϧͳ&DIP (JO *SJT͕ީิ w *SJT͕ྑͦ͞͏͕ͩɺίϛολʔͷྑ͘ͳ͍ᷚΛฉ͍ͯީิ͔Β֎ͨ͠
w &DIPͱ(JO(JUIVCελʔͱϕϯνɺϝϯςঢ়گ͔Β(JOΛબ 6
Ginͷ͍ํ w 1BUIύϥϝʔλͷݕূΛ.JEEMFXBSFʹͯ͠ɺDPOUSPMMFSͰ OBNFD.VTU(FU lVTFSOBNFz TUSJOH ͱ͠ɺίϯτϩʔϥʔΛεϦϜԽ w HJOίϚϯυ
IUUQTHJUIVCDPNDPEFHBOHTUBHJO ͰϥΠϒϦϩʔυ HPͰ࠶Ϗϧυ͕ߴʹ
O/R Ϛούʔ w (03. HPSQ 9PSN͕ީิ w HPSQϝϯςφϯε͕ࢭ·͍ͬͯΔͷͰީิ͔Β֎ͨ͠ w (03.ͱ9PSNͰ(03.ͷํ͕(JUIVCελʔ͕ଟ͍
w 9PSNͷํ͕γϯϓϧͳ"1*ͳͷͱɺຒΊࠐΈߏମରԠ͕ྑ͔ͬͨ 8
Xorm ຒΊࠐΈߏମͷྫ // User ユーザー情報を格納 type User struct { Common
`xorm:"extends"` IdentityCode string `xorm:"notnull" json:”identity_code”` UserPublicData `xorm:"extends"` CustomerID string `xorm:"" json:"customer_id"` } // UserPublicData は公開⽤のユーザー情報を格納 type UserPublicData struct { PublicID uint64 `xorm:"-" json:"id"` UserProfile `xorm:"extends"` LastLoginAt *time.Time `json:"last_login_at"` } // Common テーブル共通項⽬を定義 type Common struct { ID uint64 `xorm:"pk autoincr index(pk)" json:"id"` IsDeleted bool `xorm:"default false notnull" json:"is_deleted"` CreatedAt *time.Time `xorm:"created notnull" json:"created_at"` UpdatedAt *time.Time `xorm:"updated notnull" json:"updated_at"` } ߏମʹڞ௨ߏମΛຒΊࠐΜͰޮΑ͘.PEFMͷఆ͕ٛग़དྷΔͱ͜Ζ͕ྑ͍ xorm:”extends” json.MarshalͷΑ͏ʹ ຒΊࠐΈΛల։ͯ͘͠ΕΔ 9
ϨΠϠʔυϞσϧ ΫϦʔϯΞʔΩςΫνϟʔͱಉ͡ߏ ϧʔςΟϯάɾɾɾ"1*ΤϯυϙΠϯτͷఆٛ ίϯτϩʔϥʔɾɾɾɹϋϯυϥʔͷ࣮ αʔϏεɾɾɾϏδωεϩδοΫͷ࣮ ϦϙδτϦɾɾɾϞσϧͷΞΫηε ϞσϧɾɾɾυϝΠϯͷσʔλදݱ Πϯϑϥɾɾɾ%#ɺܾࡁαʔϏε ґଘؔ 10
ϨΠϠʔυϞσϧ ΫϦʔϯΞʔΩςΫνϟʔͱಉ͡ߏ ϧʔςΟϯάɾɾɾ"1*ΤϯυϙΠϯτͷఆٛ ίϯτϩʔϥʔɾɾɾɹϋϯυϥʔͷ࣮ αʔϏεɾɾɾϏδωεϩδοΫͷ࣮ ϦϙδτϦɾɾɾϞσϧͷΞΫηε ϞσϧɾɾɾυϝΠϯͷσʔλදݱ Πϯϑϥɾɾɾ%#ɺܾࡁαʔϏε ґଘؔ 11
͜ͷ෦ͷଓʹ αʔϏεϨδετϦ Λͬͯ
αʔϏεϨδετϦᶃ // RegistryInterface はサービスレジストリ type RegistryInterface interface { NewUser() UserInterface
} // Registry はサービスレジストリの実装 type Registry struct { engine infra.EngineInterface } // NewRegistry は依存を注⼊してサービスレジストリを初期化 func NewRegistry(engine infra.EngineInterface) RegistryInterface { return &Registry{engine} } // NewUser はUserサービスを取得 func (r *Registry) NewUser() UserInterface { userRepo := model.NewUsersRepository(r.engine) return NewUser(userRepo) } 12 wαʔϏεϨδετϦશͯͷαʔϏεΛऔಘ͢ΔΠϯλʔϑΣʔεΛ࣋ͭ
αʔϏεϨδετϦᶄ // ServiceRegistryMiddleware はサービスレジストリを提供 func ServiceRegistryMiddleware(registry service.RegistryInterface) gin.HandlerFunc { return
func(c *gin.Context) { c.Set("service", registry) c.Next() } } func GetUserByID(c *gin.Context) { // サービスレジストリから使うサービスを取得 registry := c.MustGet("service").(service.RegistryInterface) userService := registry.NewUser() 13 w.JEEMFXBSFͰɹ$POUFYUʹϨδετϦΛొ w$POUSPMMFSͰ$POUFYU͔ΒϨδετϦΛऔಘ
αʔϏεϨδετϦͷϞοΫᶃ // Registry はServiceRegistryのモック実装です type Registry struct { service.RegistryInterface FakeUser
service.UserInterface FakeShop service.ShopInterface FakeUserActivity service.UserActivityInterface FakeActivityLogger service.ActivityLoggerInterface // …略… } // NewUser はFakeUserを返す func (r *Registry) NewUser() service.UserInterface { return r.FakeUser } wςετิॿ༻ύοέʔδʹαʔϏεϨδετϦϞοΫΛ࣮͓ͯ͘͠
αʔϏεϨδετϦͷϞοΫᶄ // User はUserサービスのモック実装 type User struct { service.UserInterface FakeGetByID
func(id uint64) (*model.UserPublicData, bool) } // GetByID はFakeGetByIDを呼び出す func (u *User) GetByID(id uint64) (*model.UserPublicData, bool) { return u.FakeGetByID(id) } wରͷςετͰݺΕΔGVODͷΈࠩ͠ࠐΊΔ࡞Γ
ࠓճͷߏͰྑ͔ͬͨͱ͜Ζ ಛผͳͳ͘(PΒ͘͠ॻ͚ɺ࣮ͨ͠ϓϩάϥϜ͕҆ఆͯ͠ಈ࡞͢Δ ϢʔβʔཧɺܾࡁʹϚωʔδυαʔϏεΛָ͕ͬͯͰ͖ͨ ϨΠϠʔͱґଘؔΛ៉ྷʹ͚ͨͷͰςετඇৗʹ࡞Γ͍͢ 16
ࠔͬͨͱ͜Ζɺ͍ͨ͠ͱ͜Ζ UJNF/PX Ͱݱࡏ࣌ࠁΛऔಘ͍ͯ͠ΔͷͰɺςετͰ࣌ؒΛ֬ೝͮ͠Β͍ &$Ͱ࣮ߦ͍ͯ͠ΔͷͰɺ&$4'BSHBUFͷίϯςφϕʔεʹҠߦ͍ͨ͠ %PDLFS։ൃڥ͕EFQͷWFOEFSPSJHΛ࡞͢ΔڍಈͰ͏·͍͔͘ͳ͍ 17 WHPʹظʂ
Goݴޠ ✖ AWS ✖ ReactͰ։ൃ͢ΔؒΛืूதʂ https://www.wantedly.com/companies/gemcook 18