Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Become a gorm feeling and use gorm
Search
linyows
April 15, 2018
Programming
19k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Become a gorm feeling and use gorm
Gormの気持ちになってGormを使う
Aprio 15, 2018 @Go Conference 2018 Spring でお話しした資料です
linyows
April 15, 2018
More Decks by linyows
See All by linyows
GoとClickhouseで作るRAGアプリ / Building RAG Application with Go and Clickhouse
linyows
1
310
Kubernetesを使わない環境にもCloud Nativeなデプロイを実現する / Enabling Cloud Native deployments without the complexity of Kubernetes
linyows
3
970
Protocol Buffersの型を超えて拡張性を得る / Beyond Protocol Buffers Types Achieving Extensibility
linyows
0
330
研究開発と実装OSSと プロダクトの好循環 / A virtuous cycle of research and development implementation OSS and products
linyows
1
1k
コードジェネレーターで 効率的な開発をする / Efficient development with code generators
linyows
0
530
研究を支える拡張性の高い ワークフローツールの提案 / Proposal of highly expandable workflow tools to support research
linyows
0
770
非コンテナ環境において宣言的Deploymentを手軽に実現する / Declarative deployment in non-container environments
linyows
1
680
メール送信サーバの集約における透過型SMTP プロキシの定量評価 / Quantitative Evaluation of Transparent SMTP Proxy in Email Sending Server Aggregation
linyows
0
1.3k
透過型SMTPプロキシによる送信メールの可観測性向上: Update Edition / Improved observability of outgoing emails with transparent smtp proxy: Update edition
linyows
2
760
Other Decks in Programming
See All in Programming
Vapor Mode でアクセシビリティは 壊れないか検証した話
fuqda
1
320
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
400
AI時代のIaC入門 〜なぜインフラをコードで管理したいのか?〜 / Introduction to IaC in the AI Era
akihisaikeda
6
1.4k
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
5.1k
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
250
느린 네트워크와 저사양 디바이스 사용자를 위한 웹뷰 로딩 시간 개선기
kmkim
1
180
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
5
740
Groovy as a human and AI friendly programming language
paulk
0
180
[DroidKnights 2026] Workflow AX: From Auto-Documented Policies to E2E Testing
raeminkang
0
510
Goコンパイラを作ってGoをもっと理解する / Build a Go compiler to better understand Go
ikura_hamu
0
120
Next.js: The final boss of Web Performance
guaca
0
380
高橋メソッドでCVE解説シリーズ 〜CVE-2026-112816〜
hakkadaikon
0
200
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
42
3.2k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3.1k
We Have a Design System, Now What?
morganepeng
55
8.4k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
350
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
600
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.9k
How Software Deployment tools have changed in the past 20 years
geshan
2
35k
Abbi's Birthday
coloredviolet
4
11k
Making Projects Easy
brettharned
120
6.8k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
Rails Girls Zürich Keynote
gr2m
96
14k
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