Golang操作MySQL的正確姿勢

封裝原因:
  • 查看了很多網上提供的ORM類型的數據庫操作,覺得比較麻煩,需要提前配置很多的表結構體,然後才能使用,對於數據表很多的項目就配置起來就比較麻煩,所以對golang的mysql包進行了外層包裝,簡化在開發中的使用.
實現思路:
  • 通過配置數據庫鏈接,初始化連接(實現連接池),設置連接池參數,並存入map[string]*sql.DB中,在需要時調用.
  • 使用Struct方法,對SQL進行預處理,然後執行相應的SQL,獲取數據
配置數據庫鏈接
  • 例如我配置了三個數據庫的鏈接,分別是cms庫, base庫和sms庫,配置代碼如下
package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
)

var (
	WorkDir          string            // 項目的根目錄
	DBConfig         map[string]string // 數據庫參數配置
)

// 初始化解析Env配置文件
func init() {
	// 需要編譯後才能生效
	WorkDir = filepath.Dir(os.Args[0])
	err := os.Setenv("GOPATH", WorkDir)
	data, err := ioutil.ReadFile(path.Join(WorkDir, ".env"))
	if err != nil {
		log.Fatal(err)
	}
	result := make(map[string]string)
	// 把uint8形式轉換爲map類型數據
	// []byte(data) 對字節數組轉換成byte類型數據
	err = json.Unmarshal([]byte(data), &result)
	if err != nil {
		log.Fatal(err)
	}
	// 數據庫配置map
	dBMap := make(map[string]string)
	// 格式化數據庫鏈接
	CmsConnect := fmt.Sprintf("%s:%s@tcp(%s:%s)/cms?charset=utf8mb4", result["DB_CMS_USER"],
		result["DB_CMS_PASS"], result["DB_CMS_HOST"], result["DB_CMS_PORT"])
	BaseConnect := fmt.Sprintf("%s:%s@tcp(%s:%s)/base?charset=utf8mb4", result["DB_BASE_USER"],
		result["DB_BASE_PASS"], result["DB_BASE_HOST"], result["DB_BASE_PORT"])
	SmsConnect := fmt.Sprintf("%s:%s@tcp(%s:%s)/sms?charset=utf8mb4", result["DB_SMS_USER"],
		result["DB_SMS_PASS"], result["DB_SMS_HOST"], result["DB_SMS_PORT"])
	dBMap["cms"], dBMap["base"], dBMap["sms"] = CmsConnect, BaseConnect, SmsConnect
	DBConfig = dBMap
}
使用方法
  • 創建-Create方法, 接收參數類型爲map[string]interface{}
    (1).map中key即爲數據表的對應的字段名稱,value即爲對應要創建的數據字段值
    (2).返回結果爲新增數據在表中的ID和error信息,新增成功error爲nil
import . "mysqldb"
# 例如我想base庫的auth_user表添加一條記錄,創建的三個字段爲手機號phone,姓名real_name,性別sex
createMap := make(map[string]interface{})
createMap["phone"], createMap["name"], createMap["sex"] = "18300000000", "張三", 1
insertId, err := DB("base").Table("auth_user").Create(createMap)
  • 批量創建-BulkCreate方法,接收參數類型爲[]map[string]interface{}
    (1).返回結果爲影響的行數和error信息,新增成功error爲nil
# 例如我想base庫的auth_user表添加兩條記錄,創建的三個字段爲手機號phone,姓名real_name,性別sex
var createMap []map[string]interface{}
cMap := make(map[string]interface{})
cMap["phone"], cMap["name"], cMap["sex"] = "18300000000", "張三", 1
createMap = append(createMap, cMap)
cMap["phone"], cMap["name"], cMap["sex"] = "18300000001", "李梅", 2
createMap = append(createMap, cMap)
insertId, err := DB("base").Table("auth_user").BulkCreate(createMap)
  • 刪除-Delete方法
    (1). 通過Filter設置篩選條件
    (2).返回結果爲影響的行數和error信息,刪除成功error爲nil
# 例如我想刪除base庫的auth_user表中phone爲1830000000的記錄
affectRows, err :=DB("base").Table("auth_user").Filter("phone=?", "18300000000").Delete()
  • 更新-Update方法,接收參數類型爲map[string]interface{}
    (1). 通過Filter設置篩選條件
    (2).返回結果爲影響的行數和error信息,更新成功error爲nil
# 例如我要更新base庫的auth_user表中phone爲18300000000數據的姓名爲李四
createMap := make(map[string]interface{})
createMap["phone"], createMap["name"], createMap["sex"] = "18300000000", "李四", 1
affectRows, err := DB("base").Table("auth_user").Filter("phone=?", "18300000000").Update(createMap)
  • 查詢
    (1). 單條數據獲取爲Get,獲取查詢到的第一條數據,返回結果類型爲map[string]interface{}
    (2). 獲取所有數據爲All, 返回結果類型爲[]map[string]interface{}
# 例如我要獲取base庫auth_user表中phone爲18300000000的一條記錄
userData := DB("base").Table("auth_user").Filter("phone=?", "18300000000").Get()
# 例如我要獲取base庫auth_user表中phone爲18300000000的所有記錄
userData := DB("base").Table("auth_user").Filter("phone=?", "18300000000").All()
# 例如我要獲取base庫auth_user表中phone爲18300000000按照ID降序一條記錄
userData := DB("base").Table("auth_user").Filter("phone=?", "18300000000").OrderBy("-id").Get()
  • 多多件查詢
# 例如我要獲取base庫auth_user表中phone爲18300000000,sex爲1的一條記錄
userData := DB("base").Table("auth_user").Filter("phone=? AND sex=?", "18300000000", 1).Get()
  • 分組方法查詢
# 例如我要獲取base庫auth_user表中每個手機號爲的統計數據
userData := DB("base").Table("auth_user").Select("phone", "COUNT(1) AS num").Filter("sex=?", 1).GroupBy("phone").All()
其他方法說明
  • Execute, 執行一條SQL,返回影響的行數和error信息.error爲nil,表示執行成功
  • FetchOne, 執行一條SQL返回一條數據結果,返回結果類型爲: map[string]interface{}
  • FetchAll, 執行一條SQL,返回多條數據結果,返回結果類型爲: []map[string]interface{}
未實現方法
  • 多表關聯查詢,建議通過書寫原生SQL,然後使用FetchOne或FetchAll方法執行獲取數據
源代碼地址
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章