Become a gorm feeling and use gorm

5d769d109697012317c09c6a27a6a4bf?s=47 linyows
April 15, 2018

Become a gorm feeling and use gorm

Gormの気持ちになってGormを使う
Aprio 15, 2018 @Go Conference 2018 Spring でお話しした資料です

5d769d109697012317c09c6a27a6a4bf?s=128

linyows

April 15, 2018
Tweet

Transcript

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

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

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

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

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

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

  7. (P$POGFSFODF4QSJOH (PSN࢖ͬͨ͜ͱ͋Γ·͔͢ʁ ▸ 03.0CKFDU3FMBUJPOBM.BQQFS ▸ ଟ෼ɺ(PͰ͸Ұ൪ϝδϟʔͳ03. ▸ (PSNͷଞʹ͸HPSQ YPSN TRMY

    ▸ ΄͔ͷݴޠͩͱɺ"DUJWF3FDPSE 3VCZ &MPRVFOU 1)1  4FRVFMJ[F /PEFKT  "DUJWF3FDPSEͷѹ౗త׬੒౓ʜʜʜʜ
  8. (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ͷ࢖͍ํ
  9. গͳ͍ίʔυྔͰςʔϒϧߦΛߏ଄ମʹ Ϛοϐϯάͯ͘͠ΕΔ %#ίωΫγϣϯͱߏ଄ମʢϞσϧʣΛ ෼͚ͯ࢖͏ (P$POGFSFODF4QSJOH

  10. (P$POGFSFODF4QSJOH (PSNͷػೳ ▸ "TTPDJBUJPOTIBTNBOZ CFMPOHTUP QPMZNPSQIJTN ▸ )PPLTCFGPSFBGUFS ▸ 1SFMPBEJOH

    ▸ 5SBOTBDUJPOT ▸ $PNQPTJUF1SJNBSZ,FZ
  11. 'VMM'FBUVSFE03. BMNPTU  (P$POGFSFODF4QSJOH

  12. (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Ͱ͸௝͍͠ϝιουνΣʔϯ ϝιουνΣʔϯͳͷͰಈతͳΫΤϦ࡞੒͕؆୯Ͱ͖Δ ϝιουνΣʔϯͷͨΊʹΤϥʔΛߏ଄ମʹೖΕ͍ͯΔ
  13. (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ͷϞσϧఆٛ
  14. (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
  15. Ϟσϧʹ ؔ਺ɺϝιουཚཱ໰୊ (P$POGFSFODF4QSJOH

  16. (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 ·͋ɺ΍Γ͍ͨ͜ͱ͸Θ͔Δ
  17. (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 ଞͷϞσϧґଘΛ௥Ճʜ
  18. (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 ͋Ε΍͜Ε΍௥Ճ͞Ε·ͯ͠ʜ
  19. (P$POGFSFODF4QSJOH

  20. (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 ͏·͘΍͍ͬͯΔ෩ʜ
  21. (P$POGFSFODF4QSJOH (u *User) FindByName(n string) error { if err :=

    db. First(u, "name = ?", n).Error; err != nil { return err } return nil } Ϟσϧͷཚཱؔ਺ɺϝιου1BSU ͪΐͬͱ͓Μͳ͡΍Μ
  22. (P$POGFSFODF4QSJOH ͜Ε͸͍͔Μʜ ▸ ࠣࡉͳҧ͍Ͱؔ਺΍ϝιου͕ྔ࢈͞Ε͍ͯΔ ▸ ςετίʔυͳͲɺ؅ཧίετ΋૿͍͑ͯΔ ▸ ଞͷϞσϧґଘɺόάͷԹচ

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

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

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

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

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

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

  29. (P$POGFSFODF4QSJOH (Pʹ͓͍ͯͷ"3σβΠϯ ▸ 5BCMF'VODUJPO  ▸ 5BCMF3PX4USVDU  ▸ 5BCMF3PXT4MJDF

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

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

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

  33. (P$POGFSFODF4QSJOH

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

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

  36. (P$POGFSFODF4QSJOH DMBTT JOTUBODF WBSJBCMFT %#DPOOFDUJPO GVOD %# DPOOFDUJPO TUSVDU NFUIPE

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

  38. (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 } มߋલ
  39. (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) } มߋޙ ͜Ε͚ͩʂϞσϧଆͷ࣮૷͸ແ͘ͳΓ·ͨ͠
  40. %#ૢ࡞͸(PSNʹ೚ͤΔ ˣ ৑௕͕͞ഉআ͞ΕεοΩϦ (P$POGFSFODF4QSJOH

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

  42. (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)
  43. (P$POGFSFODF4QSJOH ·ͱΊ ▸ (P͸σʔλͱৼΔ෣͍Λ෼཭͍ͯ͠Δ͜ͱΛ๨Εͳ͍ ▸ $MBTTੈքͷ"DUJWF3FDPSEͷ͜ͱ͸๨ΕΑ͏ ▸ (PSNͷ%#ίωΫγϣϯΛϞσϧʹΧϓηϧԽ͠ͳ͍ ▸ ͜ΕΒΛ౿·͑Ε͹ίʔυ͕؆ૉԽ͢Δ

    ▸ ͦͯ͠4DPQF͸݁ߏ࢖͑ΔΑ
  44. ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ (P$POGFSFODF4QSJOH