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
2.7k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go言語でAPIサーバーを実装しました
GoでCtoCサービスのAPIサーバーを実装した構成
今回の構成で良かったところ
困ったところ、直したいところ
yoskeoka
February 24, 2018
More Decks by yoskeoka
See All by yoskeoka
フロントエンドの変遷がもたらしたバックエンドの進化
yoskeokamoto
3
780
Other Decks in Technology
See All in Technology
アクセスキーが漏れた日にやるべきこと- 無効化の先にある本当の対応
kazzpapa3
0
170
Flutter × BLE Centralを自前Pluginで実装する設計パターン - MethodChannel / EventChannelで作る双方向ブリッジの実践 / Building Custom Flutter BLE Central Plugins: Bidirectional Bridging with Method & Event Channels
bitkey
PRO
0
210
平文パスワードはログに“残り” ── 肝心の侵入は“痕跡すら残らない”
kuroneko13
0
120
会社紹介資料 / Sansan Company Profile
sansan33
PRO
24
430k
MIXIで活躍できるエンジニアを 若手社員目線で考えてみる
mixi_engineers
PRO
0
120
英語が話せなくてもKubeConスタッフに参加した話
yusuke427
2
1.1k
AIに持続⼒を与える 判断の⻑期記憶設計
eiei114
1
590
Invisible to AI? Making TYPO3 Sites Quotable by AI Search Systems
wolfgangwagner
0
240
Android skills に学ぶ
kokiko
0
140
AIに狂うスタートアップが、あえて「人との協働」に全振りした新卒エンジニア研修 / New Graduate Engineer Training at a Startup Accelerating AI Adoption
ohnoeight
0
180
[potatotips #96] Give Your AI Agent the Flutter Playbook
korodroid
0
130
Kiro Crew入門 - 常駐エージェントの仕組みと使いどころ / Intro to Kiro Crew
k_adachi_01
1
720
Featured
See All Featured
Navigating Weather and Climate Data
rabernat
0
490
How STYLIGHT went responsive
nonsquared
100
6.2k
Evolving SEO for Evolving Search Engines
ryanjones
0
260
The Curse of the Amulet
leimatthew05
2
14k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
How to train your dragon (web standard)
notwaldorf
97
6.8k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
640
Making the Leap to Tech Lead
cromwellryan
135
10k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
800
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
440
The Spectacular Lies of Maps
axbom
PRO
1
940
YesSQL, Process and Tooling at Scale
rocio
174
15k
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