後端系統其實最核心的就是與資料庫進行互動,我在寫rails時有一個module就是負責與資料庫的互動- ActiveRecord,這個module最核心的就是把record包裝成實體物件,也可以說是映射到ruby的物件上,於是乎,我就可以很方便的處理這些物件,我很依賴這樣子的處理方式,但必須說,這前提都是建立在物件導向語言上
然而,要知道go並不是一個物件導向語言,Go 傾向於提供較少的特性,並強調簡單和效能。這些特性使得 Go 在某些方面(例如並發)表現出色,但在其他方面(例如物件關聯映射(ORM))可能不是那麼直觀或易用,像是ORM
故,再go的後端系統上選擇實作orm時,一定要考慮這些問題
但好在,現在有一個穩定的orm package,今天我們就要來介紹這個package
gorm 是一個用於 Go 語言的 Object Relational Mapping (ORM) 庫,它封裝了 database/sql 的許多功能,並提供了一個更高級的接口來與數據庫進行交互
所以前幾天說到的database/sql的功能,我們會依賴gorm 來幫我們完成
db docking:
package main
import (
  "gorm.io/gorm"
  "gorm.io/driver/sqlite"
)
db open:
func main() {
  db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
  if err != nil {
    panic("failed to connect database")
  }
}
接下來我們來看看基本用法吧
在 GORM中,當我們談到"模型",我們通常是指用來代表和操作數據庫表的 Go 結構體。這些結構體包含一些字段,這些字段的類型通常是:
基本 Go 類型:例如 string、int、float64 等,用於儲存常見的數據類型
指針或別名:例如 *string 或 *int,允許字段為 nil,在數據庫中表示為 NULL 值,別名就是你為現有的類型定義的一個新名字,例如 type Age int。
自定義類型:這些類型實現了 Scanner 和 Valuer 接口,允許你自定義如何將數據讀取到 Go 程序中(Scanner)和如何將 Go 程序中的數據保存到數據庫中(Valuer),這對於處理數據庫中的特殊類型(例如 JSON、ENUM 等)或執行自定義數據處理非常有用。
type User struct {
  ID           uint
  Name         string
  Email        *string
  Age          uint8
  Birthday     *time.Time
  MemberNumber sql.NullString
  ActivatedAt  sql.NullTime
  CreatedAt    time.Time
  UpdatedAt    time.Time
}
GORM 傾向於選擇慣例優於配置,默認情況下,GORM 使用 ID 作為主鍵,將結構名複數化並轉換為 snake_case 作為表名,使用 snake_case 作為列名,並使用 CreatedAt 和 UpdatedAt 來表示建立時間/更新時間
這是GORM的慣例,當然也可以打破慣例,可以多參考官方的說明書
PostgreSQL
import (
  "gorm.io/driver/postgres"
  "gorm.io/gorm"
)
dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
result := db.Create(&user) // pass pointer of data to Create
user.ID             // returns inserted data's primary key
result.Error        // returns error
result.RowsAffected // returns inserted records count
GORM 提供了 First、Take 和 Last 方法來實現這一點,並在查詢數據庫時添加了 LIMIT 1 條件。如果沒有找到記錄,它將返回 ErrRecordNotFound 錯誤
也提供where查詢
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// Get all matched records
db.Where("name <> ?", "jinzhu").Find(&users)
// SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
db.First(&user)
user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)
// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;
// Email's ID is `10`
db.Delete(&email)
// DELETE from emails where id = 10;
// Delete with additional conditions
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
示例參考 gorm