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
180
研究開発と実装OSSと プロダクトの好循環 / A virtuous cycle of research and development implementation OSS and products
linyows
1
750
コードジェネレーターで 効率的な開発をする / Efficient development with code generators
linyows
0
390
研究を支える拡張性の高い ワークフローツールの提案 / Proposal of highly expandable workflow tools to support research
linyows
0
570
非コンテナ環境において宣言的Deploymentを手軽に実現する / Declarative deployment in non-container environments
linyows
1
430
メール送信サーバの集約における透過型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
570
研究の再現性を高める 仕組みをGoでつくる / Creating a system to improve the reproducibility of research using go
linyows
1
310
奥が深いメールのシステム / The depth of Email system
linyows
4
730
Other Decks in Programming
See All in Programming
Cell-Based Architecture
larchanjo
0
150
SwiftUIで本格音ゲー実装してみた
hypebeans
0
510
メルカリのリーダビリティチームが取り組む、AI時代のスケーラブルな品質文化
cloverrose
2
390
ローカルLLMを⽤いてコード補完を⾏う VSCode拡張機能を作ってみた
nearme_tech
PRO
0
180
PostgreSQLで手軽にDuckDBを使う!DuckDB&pg_duckdb入門/osc25hi-duckdb
takahashiikki
0
180
AI前提で考えるiOSアプリのモダナイズ設計
yuukiw00w
0
190
クラウドに依存しないS3を使った開発術
simesaba80
0
180
Combinatorial Interview Problems with Backtracking Solutions - From Imperative Procedural Programming to Declarative Functional Programming - Part 2
philipschwarz
PRO
0
120
AIエンジニアリングのご紹介 / Introduction to AI Engineering
rkaga
8
3.4k
Implementation Patterns
denyspoltorak
0
130
tparseでgo testの出力を見やすくする
utgwkk
2
290
実はマルチモーダルだった。ブラウザの組み込みAI🧠でWebの未来を感じてみよう #jsfes #gemini
n0bisuke2
3
1.3k
Featured
See All Featured
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
680
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.2k
Building the Perfect Custom Keyboard
takai
1
660
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
1
210
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
A designer walks into a library…
pauljervisheath
210
24k
How to Ace a Technical Interview
jacobian
281
24k
WENDY [Excerpt]
tessaabrams
8
35k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
61k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
150
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