golang基礎-和mysql打交道

mysql簡介

mysql是關係型數據庫RDBMS(Relational database management system)的典型表明,也是後臺開發中打交道最多的一個組件。mysql

go-sql-driver訪問數據庫

插入操做

func InsertUser(user bean.User) (bool){
  //開啓事務
  tx, err := DB.Begin()
  if err != nil{
      fmt.Println("tx fail")
      return false
  }
  //準備sql語句
  stmt, err := tx.Prepare("INSERT INTO nk_user (`name`, `password`) VALUES (?, ?)")
  if err != nil{
      fmt.Println("Prepare fail")
      return false
  }
  //將參數傳遞到sql語句中而且執行
  res, err := stmt.Exec(user.UserName, user.Password)
  if err != nil{
      fmt.Println("Exec fail")
      return false
  }
  //將事務提交
  tx.Commit()
  //得到上一個插入自增的id
  fmt.Println(res.LastInsertId())
  return true
}
複製代碼

查詢操做

func SelectAllUser() ([]bean.User) {
    //執行查詢語句
    rows, err := DB.Query("SELECT * from nk_user")
    if err != nil{
        fmt.Println("查詢出錯了")    
    }
    var users []bean.User
    //循環讀取結果
    for rows.Next(){
        var user bean.User
        //將每一行的結果都賦值到一個user對象中
        err := rows.Scan(&user.Id, &user.UserName, &user.Password)
        if err != nil {
            fmt.Println("rows fail")
        }
        //將user追加到users的這個數組中
        users = append(users, user)
    }
    return users
}
複製代碼

這裏會發現,當字段比較多,有二三十個,sql語句都須要本身寫,同時scan還得指定每個字段去接收,若是類型同樣的錯位了,就是一個難以排查的事故。 同時,sql語句太長,也很差維護。在大型項目開發過程當中,幾乎全部團隊都會選擇用orm。git

golang 的gorm

什麼是orm

ORM全稱是:Object Relational Mapping(對象關係映射),其主要做用是在編程中,把面向對象的概念跟數據庫中表的概念對應起來。舉例來講就是,我定義一個對象,那就對應着一張表,這個對象的實例,就對應着表中的一條記錄。github

鏈接數據庫

import (
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

func main() {
  db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
  defer db.Close()
}
複製代碼

建立記錄

user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}

db.NewRecord(user) // => returns `true` as primary key is blank

db.Create(&user)

db.NewRecord(user) // => return `false` after `user` created
複製代碼

查詢記錄

// Get first record, order by primary key
db.First(&user)
//// SELECT * FROM users ORDER BY id LIMIT 1;

// Get last record, order by primary key
db.Last(&user)
//// SELECT * FROM users ORDER BY id DESC LIMIT 1;

// Get all records
db.Find(&users)
//// SELECT * FROM users;

// Get record with primary key (only works for integer primary key)
db.First(&user, 10)
//// SELECT * FROM users WHERE id = 10;
複製代碼

查詢條件

// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
//// SELECT * FROM users WHERE name = 'jinzhu' limit 1;

// Get all matched records
db.Where("name = ?", "jinzhu").Find(&users)
//// SELECT * FROM users WHERE name = 'jinzhu';

db.Where("name <> ?", "jinzhu").Find(&users)

// IN
db.Where("name in (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)

// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)

// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)

// Time
db.Where("updated_at > ?", lastWeek).Find(&users)

db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
複製代碼

Save命令

db.Save(&data) gorm支持一個Save命令,其語意是當model中Id主鍵有值時,更新該model。無值時建立一條。若是是須要先從數據庫讀model,再更新寫入,就很適合用Save操做。golang

gorm 特性

鏈式組合

gromdb是鏈式的結構: 每一個操做返回的都是gorm.DB db.Where().Limit().Offset()sql

在業務開發中,能夠靈活運用,好比有type類型,status狀態兩個字段,若是填了才過濾,不填就返回全部的,能夠按下面這樣寫:數據庫

if status != "" {
    db.Where("status = ?", status)
}
if type != 0 "" {
    db.Where("type = ?", type)
}
db.Find([]*Data)
複製代碼

callback

callback是一個不得不提的能力,顧名思義,回調,即 經過它能夠方便地對gorm進行二次封裝。目前gorm 支持以下callback編程

  • BeforeSave : Save操做以前
  • BeforeCreate :Create操做以前
  • AfterUpdate:Update操做以後
  • AfterSave:Save操做以後
  • BeforeDelete:Delete操做以前
  • AfterDelete:Delete操做以後
  • AfterFind:Find以後

好比,若是有加密需求,就能夠在beforeCreate時運用加密。 在afterFind運用解祕。如下是一個簡單的條件判斷示例:數組

func (u *User) BeforeUpdate() (err error) {
    if u.readonly() {
        err = errors.New("read only user")
    }
    return
}

// Rollback the insertion if user's id greater than 1000 func (u *User) AfterCreate() (err error) { if u.Id > 1000 { err = errors.New("user id is already greater than 1000") } return } 複製代碼

若是callback中有失敗,那麼整個事物都會回滾。bash

開發模式推薦

單獨建一個model文件夾,一個model一個文件,能夠理解爲一個表一個文件。 在其中用類型的方法,封裝好針對這個model直接訪問的方法。 同時定義個對外暴露的變量Nsp,外面直接經過這個Nsp訪問方法。 若是有針對多表的訪問和聯合,應該再封裝一個更高層。這樣代碼結構會比較清晰。app

相關文章
相關標籤/搜索