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
Become a gorm feeling and use gorm
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
linyows
April 15, 2018
Programming
9
19k
Become a gorm feeling and use gorm
Gormの気持ちになってGormを使う
Aprio 15, 2018 @Go Conference 2018 Spring でお話しした資料です
linyows
April 15, 2018
Tweet
Share
More Decks by linyows
See All by linyows
Protocol Buffersの型を超えて拡張性を得る / Beyond Protocol Buffers Types Achieving Extensibility
linyows
0
210
研究開発と実装OSSと プロダクトの好循環 / A virtuous cycle of research and development implementation OSS and products
linyows
1
830
コードジェネレーターで 効率的な開発をする / Efficient development with code generators
linyows
0
430
研究を支える拡張性の高い ワークフローツールの提案 / Proposal of highly expandable workflow tools to support research
linyows
0
610
非コンテナ環境において宣言的Deploymentを手軽に実現する / Declarative deployment in non-container environments
linyows
1
520
メール送信サーバの集約における透過型SMTP プロキシの定量評価 / Quantitative Evaluation of Transparent SMTP Proxy in Email Sending Server Aggregation
linyows
0
1.1k
透過型SMTPプロキシによる送信メールの可観測性向上: Update Edition / Improved observability of outgoing emails with transparent smtp proxy: Update edition
linyows
2
610
研究の再現性を高める 仕組みをGoでつくる / Creating a system to improve the reproducibility of research using go
linyows
1
340
奥が深いメールのシステム / The depth of Email system
linyows
4
760
Other Decks in Programming
See All in Programming
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
510
猫の手も借りたい!ので AIエージェント猫を作って社内に放した話 Claude Code × Container Lambda の Slack Bot "DevNeko"
naramomi7
0
260
GC言語のWasm化とComponent Modelサポートの実践と課題 - Scalaの場合
tanishiking
0
110
AI Assistants for Your Angular Solutions
manfredsteyer
PRO
0
140
オブザーバビリティ駆動開発って実際どうなの?
yohfee
3
850
20260313 - Grafana & Friends Taipei #1 - Kubernetes v1.36 的開發雜記:那些困在 Alpha 加護病房太久的 Metrics
tico88612
0
200
SourceGeneratorのマーカー属性問題について
htkym
0
200
AIに任せる範囲を安全に広げるためにやっていること
fukucheee
0
130
new(1.26) ← これすき / kamakura.go #8
utgwkk
0
2.3k
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
520
Go Conference mini in Sendai 2026 : Goに新機能を提案し実装されるまでのフロー徹底解説
yamatoya
0
590
AIとペアプロして処理時間を97%削減した話 #pyconshizu
kashewnuts
1
240
Featured
See All Featured
GitHub's CSS Performance
jonrohan
1032
470k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
310
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
730
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
200
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
260
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
480
The Mindset for Success: Future Career Progression
greggifford
PRO
0
280
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
220
Tell your own story through comics
letsgokoyo
1
840
Writing Fast Ruby
sferik
630
63k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Practical Orchestrator
shlominoach
191
11k
Transcript
5PNPIJTB0EB(.01FQBCP *OD "QSJM (PSNͷؾ࣋ͪʹͳͬͯ(PSNΛ͏ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH ʘԬ͔Βདྷ·ͨ͠ʗ !NPOPDISPNFHBOF͞Μͨͪͱ 'VLVPLBHPΛӡӦ͍ͯ͠·͢ ࣸਅɿԬࢢ
(P$POGFSFODF4QSJOH (.0ϖύϘϓϦϯγύϧΤϯδχΞ খాԝ!MJOZPXT ٕज़෦ٕज़ج൫νʔϜ IUUQUPNPIJTBPEBDPN
(P$POGFSFODF4QSJOH ϩϦοϓʂ ϚωʔδυΫϥυ ·ͳ͘ ਖ਼ࣜ൛ϦϦʔε
(P$POGFSFODF4QSJOH ݄ʹൃചͷ 8&# %#13&44WPM )BTIJ$PSQ7BVMUͷ هࣄΛدߘ͠·ͨ͠ ͜Ε
(P$POGFSFODF4QSJOH MJOVYϢʔβͷ໊લղܾΛ HJUIVCνʔϜίϥϘϨʔλͰ ߦ͏ιϑτΣΞΛ࡞͍ͬͯ·͢ IUUQTHJUIVCDPNMJOZPXTPDUPQBTT
(P$POGFSFODF4QSJOH (PSNͬͨ͜ͱ͋Γ·͔͢ʁ ▸ 03.0CKFDU3FMBUJPOBM.BQQFS ▸ ଟɺ(PͰҰ൪ϝδϟʔͳ03. ▸ (PSNͷଞʹHPSQ YPSN TRMY
▸ ΄͔ͷݴޠͩͱɺ"DUJWF3FDPSE 3VCZ &MPRVFOU 1)1 4FRVFMJ[F /PEFKT "DUJWF3FDPSEͷѹతʜʜʜʜ
(P$POGFSFODF4QSJOH type Product struct { gorm.Model Code string Price uint
} func main() { db, _ := gorm.Open("sqlite3", "test.db") defer db.Close() db.Create(&Product{Code: "L1212", Price: 1000}) var p Product db.First(&p, 1) db.First(&p, "code = ?", "L1212") db.Model(&p).Update("Price", 2000) db.Delete(&p) } (PSNͷ͍ํ
গͳ͍ίʔυྔͰςʔϒϧߦΛߏମʹ Ϛοϐϯάͯ͘͠ΕΔ %#ίωΫγϣϯͱߏମʢϞσϧʣΛ ͚ͯ͏ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH (PSNͷػೳ ▸ "TTPDJBUJPOTIBTNBOZ CFMPOHTUP QPMZNPSQIJTN ▸ )PPLTCFGPSFBGUFS ▸ 1SFMPBEJOH
▸ 5SBOTBDUJPOT ▸ $PNQPTJUF1SJNBSZ,FZ
'VMM'FBUVSFE03. BMNPTU (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH err := db.Debug().Where("role = ?", "admin").Or("role = ?", "super").Find(&users).Error
// SELECT * FROM users WHERE role = 'admin' OR role = 'super'; (PSNͷಛ (PͰ͍͠ϝιουνΣʔϯ ϝιουνΣʔϯͳͷͰಈతͳΫΤϦ࡞͕؆୯Ͱ͖Δ ϝιουνΣʔϯͷͨΊʹΤϥʔΛߏମʹೖΕ͍ͯΔ
(P$POGFSFODF4QSJOH package gorm type Model struct { ID uint `gorm:"primary_key"`
CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time `sql:"index"` } package model type User struct { gorm.Model Name string } (PSNͷϞσϧఆٛ
(P$POGFSFODF4QSJOH $ find model -type f -not -name '*_test.go' |
wc -l 35 $ find model -type f -not -name '*_test.go' | xargs grep 'func' | grep -v '\sfunc' | wc -l 196 # ???????????????? ଟ͘ͳ͍ʁ $ find api -type f -not -name '*_test.go' | wc -l 22 (PSNΛར༻ͨ͠ɺ͋Δ"1*4FSWFS
Ϟσϧʹ ؔɺϝιουཚཱ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH func FindUserByName(n string) *User, error { u := new(User)
if err := db. First(u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ·͋ɺΓ͍ͨ͜ͱΘ͔Δ
(P$POGFSFODF4QSJOH func FindUserByNameWithProfile(n string) *User, error { u := new(User)
if err := db. Preload("Profile").First(u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ଞͷϞσϧґଘΛՃʜ
(P$POGFSFODF4QSJOH func FindUserByNameWithAll(n string) *User, error { u := new(User)
if err := db. Preload("Profile"). Preload("Projects"). Preload("Projects.Repositories"). Preload("Roles").First(u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ͋Ε͜ΕՃ͞Ε·ͯ͠ʜ
(P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH func FindUserByName(n string, Preload ...string) *User, error { d
:= db for _, v := range preloads { d = d.Preload(v) } u := new(User) if err := d.First(&u, "name = ?", n).Error; err != nil { return nil, err } return u, nil } Ϟσϧͷཚཱؔɺϝιου1BSU ͏·͍ͬͯ͘Δ෩ʜ
(P$POGFSFODF4QSJOH (u *User) FindByName(n string) error { if err :=
db. First(u, "name = ?", n).Error; err != nil { return err } return nil } Ϟσϧͷཚཱؔɺϝιου1BSU ͪΐͬͱ͓Μͳ͡Μ
(P$POGFSFODF4QSJOH ͜Ε͍͔Μʜ ▸ ࠣࡉͳҧ͍Ͱؔϝιου͕ྔ࢈͞Ε͍ͯΔ ▸ ςετίʔυͳͲɺཧίετ૿͍͑ͯΔ ▸ ଞͷϞσϧґଘɺόάͷԹচ
Կ͕ਖ਼͍͠ͷ͔Θ͔ΒΜ͕ Կ͔ؒҧ͍͑ͯΔ͜ͱΘ͔ͬͨ (PSNͷؾ࣋ͪʹͳΖ͏ (P$POGFSFODF4QSJOH
%#ίωΫγϣϯͱߏମʢϞσϧʣΛ͚ͯ͏͔Β ͍ΘΏΔ.7$Ͱߟ͑ΔͱɺϞσϧʹผϨΠϠʔͰ͋Δ%#ૢ࡞ΛӅ ณ͢Δͷ͕ࣗવʁ ͋ΒͨΊͯ"DUJWF3FDPSEత03.Λߟ͑Δ (P$POGFSFODF4QSJOH Ͳ͏ͯ͜͠͏ͳͬͨʁ ▸ ͞ΕͨͭΛͭʹϥοϓͨ͘͠ͳΔ ▸ ΫΤϦͷ࡞ΓํͰऔಘͰ͖Δߏମ͕มԽ͢Δ
"DUJWF3FDPSE%FTJHO1BUUFSO "OPCKFDUUIBUXSBQTBSPXJOBEBUBCBTFUBCMFPSWJFX FODBQTVMBUFTUIFEBUBCBTFBDDFTT BOEBEETEPNBJOMPHJDPOUIBU EBUB .BSUJO'PXMFS
ςʔϒϧͷߦΛΧϓηϧԽͨ͠ΦϒδΣΫτʹ υϝΠϯϩδοΫΛੜ͢ύλʔϯ (P$POGFSFODF4QSJOH ͭ·Γ
(P$POGFSFODF4QSJOH 3VCZʹ͓͍ͯͷ"3σβΠϯ ▸ 5BCMF$MBTT ▸ 5BCMF3PX*OTUBODF ▸ 5BCMF3PXT"SSBZ ▸ %PNBJO-PHJD*OTUBODF.FUIPE
(P$POGFSFODF4QSJOH user = new User(name: 'linyows') user.save() 3VCZʹ͓͍ͯͷ"3σβΠϯ Πϯελϯε͔ΒอଘͰ͖Δ ͳͥͳΒΫϥεʹ%#ίωΫγϣϯΛแ͍ͯ͠Δ͔Β
(P$POGFSFODF4QSJOH (Pʹ͓͍ͯͷ"3σβΠϯ ▸ 5BCMF'VODUJPO ▸ 5BCMF3PX4USVDU ▸ 5BCMF3PXT4MJDF
▸ %PNBJO-PHJD.FUIPE ͘͢ͳ͘ͱɺ(PSNʹ͓͍ͯ͜͏ͩ
(P$POGFSFODF4QSJOH u := User{Name: "linyows"} db.Save(&u) (Pʹ͓͍ͯͷ"3σβΠϯ ECίωΫγϣϯ͔ΒσʔλΛอଘ͢Δ ߏମͨͩͷೖΕͳͷͰɺવΫϥεͷΑ͏ʹৼΔ͑ͳ͍
σβΠϯͱͯ͠ͳͦ͞͏ (P$POGFSFODF4QSJOH
͋ΒͨΊͯ(Pͷݴޠ༷Λ֬ೝ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH
ΑΓॏཁͳΞΠσΞίϯηϓτͷɻ σʔλͱৼΔ͍ɺ(PͷͭͷҟͳΔίϯηϓτͰ͋Γɺ ʮΫϥεʯͱ͍͏୯Ұͷ֓೦ʹ·ͱΊΒΕ͍ͯͳ͍ɻ (P$POGFSFODF4QSJOH
ͭ·Γɺ͜ͷݴޠ༷ͷҧ͍͕͋ΔʹؔΘΒͣɺ HPSNͷϝιουνΣʔϯςʔϒϧϚοϐϯά͕"3తͰɺ HPSNͷ͍ํΛޡͬͨํʹಋ͍͍ͯΔͷͰʁ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH DMBTT JOTUBODF WBSJBCMFT %#DPOOFDUJPO GVOD %# DPOOFDUJPO TUSVDU NFUIPE
6TFS 3VCZ (P ֤ίϯϙʔωϯτ͕͞ΕΞΫηε͍͢͠ Ϟσϧ Ϟσϧ
(P$POGFSFODF4QSJOH 3BJMTͷ"DUJWF3FDPSEΕΑ͏ ▸ (Pͷ%#ίωΫγϣϯͱσʔλɺυϝΠϯϩδοΫͷΛϝ Ϧοτͱଊ͑Δ ▸ ແ༻ͷΧϓηϧԽ͠ͳ͍ ▸ ݺͼग़͠ଆʹॊೈੑΛ࣋ͨͤΔ
(P$POGFSFODF4QSJOH package api func GetUserWithProfile(c echo.Context) error { n :=
c.Param("username") u, e := model.FindUserByUsernameWithProfile(n) if e != nil { return NewError(http.StatusNotFound, e, "not found") } return c.JSON(http.StatusOK, u)) } package model func FindUserByUsernameWithProfile(n string) (*User, error) { u := new(User) if err := db.Preload("Profile").Scopes(Enabled).Where("username = ?", n).First(u).Error; err != nil { return nil, err } return u, nil } มߋલ
(P$POGFSFODF4QSJOH package api func GetUserWithProfile(c echo.Context) error { n :=
c.Param("username") u := new(model.User) if err := db.Preload("Profile").Scopes(Enabled).Where("username = ?", n).First(u).Error; err != nil { return NewError(http.StatusNotFound, e, "not found") } return c.JSON(http.StatusOK, f) } มߋޙ ͜Ε͚ͩʂϞσϧଆͷ࣮ແ͘ͳΓ·ͨ͠
%#ૢ࡞(PSNʹͤΔ ˣ ͕͞ഉআ͞ΕεοΩϦ (P$POGFSFODF4QSJOH
શͯ(PSNͷؾ࣋ͪ (P$POGFSFODF4QSJOH
(P$POGFSFODF4QSJOH ৽ͨͳ՝ɿݺͼग़͠ଆʹࣅͨΑ͏ͳίʔυ͕૿͑ͳ͍ʁ 4DPQFTΛ͑େৎɺݺͼग़͠Λڞ௨Խ͢Δ͜ͱ͕Ͱ͖Δ 4DPQFɺ'VODUJPOͳͷͰϞσϧ໊Λ1SFpYʹ͢Δͱཧ͍͢͠ func UserGolden() func (db *gorm.DB) *gorm.DB
{ return func (db *gorm.DB) *gorm.DB { return db.Preload("Profile").Preload("Projects").Preload("Roles").Where("status = ?", "enabled") } } u := new(user) db.Scopes(UserGolden()).Find(u, 123)
(P$POGFSFODF4QSJOH ·ͱΊ ▸ (PσʔλͱৼΔ͍Λ͍ͯ͠Δ͜ͱΛΕͳ͍ ▸ $MBTTੈքͷ"DUJWF3FDPSEͷ͜ͱΕΑ͏ ▸ (PSNͷ%#ίωΫγϣϯΛϞσϧʹΧϓηϧԽ͠ͳ͍ ▸ ͜ΕΒΛ౿·͑Είʔυ͕؆ૉԽ͢Δ
▸ ͦͯ͠4DPQF݁ߏ͑ΔΑ
͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ (P$POGFSFODF4QSJOH