Slide 1

Slide 1 text

5PNPIJTB0EB(.01FQBCP *OD "QSJM (PSNͷؾ࣋ͪʹͳͬͯ(PSNΛ࢖͏ (P$POGFSFODF4QSJOH

Slide 2

Slide 2 text

(P$POGFSFODF4QSJOH ʘ෱Ԭ͔Βདྷ·ͨ͠ʗ !NPOPDISPNFHBOF͞Μͨͪͱ 'VLVPLBHPΛӡӦ͍ͯ͠·͢ ࣸਅɿ෱Ԭࢢ

Slide 3

Slide 3 text

(P$POGFSFODF4QSJOH (.0ϖύϘϓϦϯγύϧΤϯδχΞ খా஌ԝ!MJOZPXT ٕज़෦ٕज़ج൫νʔϜ IUUQUPNPIJTBPEBDPN

Slide 4

Slide 4 text

(P$POGFSFODF4QSJOH ϩϦοϓʂ ϚωʔδυΫϥ΢υ ·΋ͳ͘ ਖ਼ࣜ൛ϦϦʔε

Slide 5

Slide 5 text

(P$POGFSFODF4QSJOH ݄೔ʹൃചͷ 8%#13&44WPM )BTIJ$PSQ7BVMUͷ هࣄΛدߘ͠·ͨ͠ ͜Ε

Slide 6

Slide 6 text

(P$POGFSFODF4QSJOH MJOVYϢʔβͷ໊લղܾΛ HJUIVCνʔϜ΍ίϥϘϨʔλͰ ߦ͏ιϑτ΢ΣΞΛ࡞͍ͬͯ·͢ IUUQTHJUIVCDPNMJOZPXTPDUPQBTT

Slide 7

Slide 7 text

(P$POGFSFODF4QSJOH (PSN࢖ͬͨ͜ͱ͋Γ·͔͢ʁ ▸ 03.0CKFDU3FMBUJPOBM.BQQFS ▸ ଟ෼ɺ(PͰ͸Ұ൪ϝδϟʔͳ03. ▸ (PSNͷଞʹ͸HPSQ YPSN TRMY ▸ ΄͔ͷݴޠͩͱɺ"DUJWF3FDPSE 3VCZ &MPRVFOU 1)1 4FRVFMJ[F /PEFKT "DUJWF3FDPSEͷѹ౗త׬੒౓ʜʜʜʜ

Slide 8

Slide 8 text

(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ͷ࢖͍ํ

Slide 9

Slide 9 text

গͳ͍ίʔυྔͰςʔϒϧߦΛߏ଄ମʹ Ϛοϐϯάͯ͘͠ΕΔ %#ίωΫγϣϯͱߏ଄ମʢϞσϧʣΛ ෼͚ͯ࢖͏ (P$POGFSFODF4QSJOH

Slide 10

Slide 10 text

(P$POGFSFODF4QSJOH (PSNͷػೳ ▸ "TTPDJBUJPOTIBTNBOZ CFMPOHTUP QPMZNPSQIJTN ▸ )PPLTCFGPSFBGUFS ▸ 1SFMPBEJOH ▸ 5SBOTBDUJPOT ▸ $PNQPTJUF1SJNBSZ,FZ

Slide 11

Slide 11 text

'VMM'FBUVSFE03. BMNPTU (P$POGFSFODF4QSJOH

Slide 12

Slide 12 text

(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Ͱ͸௝͍͠ϝιουνΣʔϯ ϝιουνΣʔϯͳͷͰಈతͳΫΤϦ࡞੒͕؆୯Ͱ͖Δ ϝιουνΣʔϯͷͨΊʹΤϥʔΛߏ଄ମʹೖΕ͍ͯΔ

Slide 13

Slide 13 text

(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ͷϞσϧఆٛ

Slide 14

Slide 14 text

(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

Slide 15

Slide 15 text

Ϟσϧʹ ؔ਺ɺϝιουཚཱ໰୊ (P$POGFSFODF4QSJOH

Slide 16

Slide 16 text

(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 ·͋ɺ΍Γ͍ͨ͜ͱ͸Θ͔Δ

Slide 17

Slide 17 text

(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 ଞͷϞσϧґଘΛ௥Ճʜ

Slide 18

Slide 18 text

(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 ͋Ε΍͜Ε΍௥Ճ͞Ε·ͯ͠ʜ

Slide 19

Slide 19 text

(P$POGFSFODF4QSJOH

Slide 20

Slide 20 text

(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 ͏·͘΍͍ͬͯΔ෩ʜ

Slide 21

Slide 21 text

(P$POGFSFODF4QSJOH (u *User) FindByName(n string) error { if err := db. First(u, "name = ?", n).Error; err != nil { return err } return nil } Ϟσϧͷཚཱؔ਺ɺϝιου1BSU ͪΐͬͱ͓Μͳ͡΍Μ

Slide 22

Slide 22 text

(P$POGFSFODF4QSJOH ͜Ε͸͍͔Μʜ ▸ ࠣࡉͳҧ͍Ͱؔ਺΍ϝιου͕ྔ࢈͞Ε͍ͯΔ ▸ ςετίʔυͳͲɺ؅ཧίετ΋૿͍͑ͯΔ ▸ ଞͷϞσϧґଘɺόάͷԹচ

Slide 23

Slide 23 text

Կ͕ਖ਼͍͠ͷ͔Θ͔ΒΜ͕ Կ͔ؒҧ͍͑ͯΔ͜ͱ͸Θ͔ͬͨ (PSNͷؾ࣋ͪʹͳΖ͏ (P$POGFSFODF4QSJOH

Slide 24

Slide 24 text

%#ίωΫγϣϯͱߏ଄ମʢϞσϧʣΛ෼͚ͯ࢖͏͔Β ͍ΘΏΔ.7$Ͱߟ͑ΔͱɺϞσϧʹผϨΠϠʔͰ͋Δ%#ૢ࡞ΛӅ ณ͢Δͷ͕ࣗવʁ ͋ΒͨΊͯ"DUJWF3FDPSEత03.Λߟ͑Δ (P$POGFSFODF4QSJOH Ͳ͏ͯ͜͠͏ͳͬͨʁ ▸ ෼཭͞ΕͨͭΛͭʹϥοϓͨ͘͠ͳΔ ▸ ΫΤϦͷ࡞ΓํͰऔಘͰ͖Δߏ଄ମ͕มԽ͢Δ

Slide 25

Slide 25 text

"DUJWF3FDPSE%FTJHO1BUUFSO "OPCKFDUUIBUXSBQTBSPXJOBEBUBCBTFUBCMFPSWJFX FODBQTVMBUFTUIFEBUBCBTFBDDFTT BOEBEETEPNBJOMPHJDPOUIBU EBUB .BSUJO'PXMFS

Slide 26

Slide 26 text

ςʔϒϧͷߦΛΧϓηϧԽͨ͠ΦϒδΣΫτʹ υϝΠϯϩδοΫΛੜ΍͢ύλʔϯ (P$POGFSFODF4QSJOH ͭ·Γ

Slide 27

Slide 27 text

(P$POGFSFODF4QSJOH 3VCZʹ͓͍ͯͷ"3σβΠϯ ▸ 5BCMF$MBTT ▸ 5BCMF3PX*OTUBODF ▸ 5BCMF3PXT"SSBZ ▸ %PNBJO-PHJD*OTUBODF.FUIPE

Slide 28

Slide 28 text

(P$POGFSFODF4QSJOH user = new User(name: 'linyows') user.save() 3VCZʹ͓͍ͯͷ"3σβΠϯ Πϯελϯε͔Β௚઀อଘͰ͖Δ ͳͥͳΒΫϥεʹ%#ίωΫγϣϯΛ಺แ͍ͯ͠Δ͔Β

Slide 29

Slide 29 text

(P$POGFSFODF4QSJOH (Pʹ͓͍ͯͷ"3σβΠϯ ▸ 5BCMF'VODUJPO ▸ 5BCMF3PX4USVDU ▸ 5BCMF3PXT4MJDF ▸ %PNBJO-PHJD.FUIPE ͘͢ͳ͘ͱ΋ɺ(PSNʹ͓͍ͯ͸͜͏ͩ

Slide 30

Slide 30 text

(P$POGFSFODF4QSJOH u := User{Name: "linyows"} db.Save(&u) (Pʹ͓͍ͯͷ"3σβΠϯ ECίωΫγϣϯ͔ΒσʔλΛอଘ͢Δ ߏ଄ମ͸ͨͩͷೖΕ෺ͳͷͰɺ౰વΫϥεͷΑ͏ʹ͸ৼΔ෣͑ͳ͍

Slide 31

Slide 31 text

σβΠϯͱͯ͠͸໰୊ͳͦ͞͏ (P$POGFSFODF4QSJOH

Slide 32

Slide 32 text

͋ΒͨΊͯ(Pͷݴޠ࢓༷Λ֬ೝ (P$POGFSFODF4QSJOH

Slide 33

Slide 33 text

(P$POGFSFODF4QSJOH

Slide 34

Slide 34 text

ΑΓॏཁͳΞΠσΞ͸ίϯηϓτͷ෼཭ɻ σʔλͱৼΔ෣͍͸ɺ(PͷͭͷҟͳΔίϯηϓτͰ͋Γɺ ʮΫϥεʯͱ͍͏୯Ұͷ֓೦ʹ·ͱΊΒΕ͍ͯͳ͍ɻ (P$POGFSFODF4QSJOH

Slide 35

Slide 35 text

ͭ·Γɺ͜ͷݴޠ࢓༷ͷҧ͍͕͋Δʹ΋ؔΘΒͣɺ HPSNͷϝιουνΣʔϯ΍ςʔϒϧϚοϐϯά͕"3తͰɺ HPSNͷ࢖͍ํΛޡͬͨํʹಋ͍͍ͯΔͷͰ͸ʁ (P$POGFSFODF4QSJOH

Slide 36

Slide 36 text

(P$POGFSFODF4QSJOH DMBTT JOTUBODF WBSJBCMFT %#DPOOFDUJPO GVOD %# DPOOFDUJPO TUSVDU NFUIPE 6TFS 3VCZ (P ֤ίϯϙʔωϯτ͕෼཭͞ΕΞΫηε͠΍͍͢ Ϟσϧ Ϟσϧ

Slide 37

Slide 37 text

(P$POGFSFODF4QSJOH 3BJMTͷ"DUJWF3FDPSE͸๨ΕΑ͏ ▸ (Pͷ%#ίωΫγϣϯͱσʔλɺυϝΠϯϩδοΫͷ෼཭Λϝ Ϧοτͱଊ͑Δ ▸ ແ༻ͷΧϓηϧԽ͸͠ͳ͍ ▸ ݺͼग़͠ଆʹॊೈੑΛ࣋ͨͤΔ

Slide 38

Slide 38 text

(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 } มߋલ

Slide 39

Slide 39 text

(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) } มߋޙ ͜Ε͚ͩʂϞσϧଆͷ࣮૷͸ແ͘ͳΓ·ͨ͠

Slide 40

Slide 40 text

%#ૢ࡞͸(PSNʹ೚ͤΔ ˣ ৑௕͕͞ഉআ͞ΕεοΩϦ (P$POGFSFODF4QSJOH

Slide 41

Slide 41 text

શͯ͸(PSNͷؾ࣋ͪ (P$POGFSFODF4QSJOH

Slide 42

Slide 42 text

(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)

Slide 43

Slide 43 text

(P$POGFSFODF4QSJOH ·ͱΊ ▸ (P͸σʔλͱৼΔ෣͍Λ෼཭͍ͯ͠Δ͜ͱΛ๨Εͳ͍ ▸ $MBTTੈքͷ"DUJWF3FDPSEͷ͜ͱ͸๨ΕΑ͏ ▸ (PSNͷ%#ίωΫγϣϯΛϞσϧʹΧϓηϧԽ͠ͳ͍ ▸ ͜ΕΒΛ౿·͑Ε͹ίʔυ͕؆ૉԽ͢Δ ▸ ͦͯ͠4DPQF͸݁ߏ࢖͑ΔΑ

Slide 44

Slide 44 text

͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ (P$POGFSFODF4QSJOH