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
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
190
研究開発と実装OSSと プロダクトの好循環 / A virtuous cycle of research and development implementation OSS and products
linyows
1
810
コードジェネレーターで 効率的な開発をする / Efficient development with code generators
linyows
0
420
研究を支える拡張性の高い ワークフローツールの提案 / Proposal of highly expandable workflow tools to support research
linyows
0
600
非コンテナ環境において宣言的Deploymentを手軽に実現する / Declarative deployment in non-container environments
linyows
1
490
メール送信サーバの集約における透過型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
600
研究の再現性を高める 仕組みをGoでつくる / Creating a system to improve the reproducibility of research using go
linyows
1
330
奥が深いメールのシステム / The depth of Email system
linyows
4
750
Other Decks in Programming
See All in Programming
AI主導でFastAPIのWebサービスを作るときに 人間が構造化すべき境界線
okajun35
0
280
CSC307 Lecture 13
javiergs
PRO
0
300
kintone + ローカルLLM = ?
akit37
0
120
Rails Girls Tokyo 18th GMO Pepabo Sponsor Talk
yutokyokutyo
0
170
Premier Disciplin for Micro Frontends Multi Version/ Framework Scenarios @OOP 2026, Munic
manfredsteyer
PRO
0
190
Package Management Learnings from Homebrew
mikemcquaid
0
280
登壇資料を作る時に意識していること #登壇資料_findy
konifar
4
2k
AIコーディングの理想と現実 2026 | AI Coding: Expectations vs. Reality 2026
tomohisa
0
560
PostgreSQL を使った快適な go test 環境を求めて
otakakot
0
300
Amazon Bedrockを活用したRAGの品質管理パイプライン構築
tosuri13
5
890
Claude Code、ちょっとした工夫で開発体験が変わる
tigertora7571
0
170
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
300
Featured
See All Featured
Become a Pro
speakerdeck
PRO
31
5.8k
Rails Girls Zürich Keynote
gr2m
96
14k
Designing for Timeless Needs
cassininazir
0
140
Balancing Empowerment & Direction
lara
5
920
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
1
450
Context Engineering - Making Every Token Count
addyosmani
9
680
Thoughts on Productivity
jonyablonski
75
5.1k
Tell your own story through comics
letsgokoyo
1
820
Skip the Path - Find Your Career Trail
mkilby
0
67
Color Theory Basics | Prateek | Gurzu
gurzu
0
210
Measuring & Analyzing Core Web Vitals
bluesmoon
9
760
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.2k
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