這章開(kāi)始,我們將會(huì)接觸到數(shù)據(jù)庫(kù)的相關(guān)內(nèi)容,使用了gorm這個(gè)庫(kù),gorm中文文檔這里查看中文文檔。
進(jìn)行之前,要保證電腦安裝了mysql,可以看我這篇文章安裝mysql,安裝完成后,要?jiǎng)?chuàng)建數(shù)據(jù)庫(kù)和配置文件當(dāng)中的保持一致,比如app.ini中配置的數(shù)據(jù)庫(kù)名稱(chēng)為api。
使用gorm依賴(lài)
終端執(zhí)行下載gorm
go get -u github.com/jinzhu/gorm
創(chuàng)建models/models.go文件,在這個(gè)文件中創(chuàng)建初始化方法
models/models.go
package models
import (
"api/pkg/logging"
"api/pkg/setting"
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
var db *gorm.DB //數(shù)據(jù)庫(kù)實(shí)例,定義為了全局變量
func SetUp() {
var (
err error
databaseType = setting.DatabaseSetting.Type //數(shù)據(jù)庫(kù)類(lèi)型
user = setting.DatabaseSetting.User //數(shù)據(jù)庫(kù)的用戶(hù)
pass = setting.DatabaseSetting.Password //數(shù)據(jù)庫(kù)的密碼
host = setting.DatabaseSetting.Host //數(shù)據(jù)庫(kù)地址
name = setting.DatabaseSetting.Name //數(shù)據(jù)庫(kù)名稱(chēng)
)
//使用gorm鏈接數(shù)據(jù)庫(kù)
db , err = gorm.Open(databaseType,fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True",user,pass,host,name))
if err != nil {
logging.Fatal("數(shù)據(jù)庫(kù)鏈接失敗",err) //數(shù)據(jù)庫(kù)鏈接失敗是致命的錯(cuò)誤,鏈接失敗后可以關(guān)閉程序了,所以使用logging.Fatal方法
}
//設(shè)置表名稱(chēng)的前綴
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
return setting.DatabaseSetting.TablePrefix + defaultTableName
}
db.SingularTable(true) //設(shè)置禁用表名的復(fù)數(shù)形式
db.LogMode(true) //打印日志,本地調(diào)試的時(shí)候可以打開(kāi)看執(zhí)行的sql語(yǔ)句
db.DB().SetMaxIdleConns(10) //設(shè)置空閑時(shí)的最大連接數(shù)
db.DB().SetMaxOpenConns(100) //設(shè)置數(shù)據(jù)庫(kù)的最大打開(kāi)連接數(shù)
}
注意一點(diǎn),在使用gorm操作mysql數(shù)據(jù)庫(kù)的時(shí)候,不要漏掉import _ "github.com/jinzhu/gorm/dialects/mysql",否則運(yùn)行的時(shí)候會(huì)報(bào)錯(cuò)
在main.go文件中初始化
...
setting.SetUp() //初始化配置文件
logging.SetUp() //設(shè)置日志文件
models.SetUp() //設(shè)置數(shù)據(jù)庫(kù)
...
可以在終端執(zhí)行go run main.go,查看下是否鏈接mysql成功。
用戶(hù)數(shù)據(jù)庫(kù)模型
項(xiàng)目把用戶(hù)的登錄和注冊(cè)做成了一個(gè)接口,整個(gè)流程如下:

根據(jù)上述流程,設(shè)計(jì)一個(gè)簡(jiǎn)單的user表。如下
用戶(hù)表
| 字段名 | 類(lèi)型 | 描述 | 備注 |
|---|---|---|---|
| id | int | 自增長(zhǎng) ID | 主鍵 |
| create_at | date | 創(chuàng)建時(shí)間 | gorm自帶 |
| update_at | date | 更新時(shí)間 | gorm自帶 |
| deleted_at | date | 刪除時(shí)間 | gorm自帶 |
| mobile | char(11) | 手機(jī)號(hào) | 手機(jī)號(hào),因?yàn)槭枪潭ǖ?1位格式,使用char格式,加索引,唯一且不為nil |
id,create_at,update_at,deleted_at使用的是gorm.model結(jié)構(gòu)體自動(dòng)創(chuàng)建的。以后不會(huì)在文章中說(shuō)明這4個(gè)字段,但我們要知道。
先簡(jiǎn)單的創(chuàng)建了一個(gè)mobile供我們使用,后續(xù)會(huì)添加例如name...字段,使用gorm的自動(dòng)維護(hù)。
在models/user.go文件中創(chuàng)建用戶(hù)模型
package models
import "github.com/jinzhu/gorm"
type User struct {
gorm.Model //會(huì)自動(dòng)添加id,created_at,updated_at,deleted_at四個(gè)字段,可以進(jìn)入看下類(lèi)型
Mobile string `gorm:"type:char(11);index;unique;not null;" json:"mobile,omitempty"` //手機(jī)號(hào),加索引,唯一,不為空
}
這樣的話(huà),就定義了一個(gè)簡(jiǎn)單的user模型。然后就交給gorm,讓它來(lái)根據(jù)模型創(chuàng)建數(shù)據(jù)表。
models/models.go
...
db.LogMode(true) //打印日志,本地調(diào)試的時(shí)候可以打開(kāi)看執(zhí)行的sql語(yǔ)句
db.AutoMigrate(&User{}) //自動(dòng)檢查 Tag 結(jié)構(gòu)是否變化,變化則進(jìn)行遷移,需要的參數(shù)為數(shù)據(jù)庫(kù)模型結(jié)構(gòu)體
...
使用AutoMigrate方法,可以自動(dòng)維護(hù),只要把定義好的結(jié)構(gòu)體傳入即可。然后重新執(zhí)行go run main.go

可以看到成功的創(chuàng)建了用戶(hù)表。
后期需要在user表中添加新的字段,比如name,age等,就可以直接在結(jié)構(gòu)體中添加,重新run一下,gorm就會(huì)自動(dòng)幫我們維護(hù)數(shù)據(jù)表了。
根據(jù)項(xiàng)目的需求,整理了一下user表所需要的字段:
用戶(hù)表
| 字段名 | 類(lèi)型 | 描述 | 備注 |
|---|---|---|---|
| id | int | 自增長(zhǎng) ID | 主鍵 |
| mobile | char(11) | 手機(jī)號(hào) | 手機(jī)號(hào),因?yàn)槭枪潭ǖ?1位格式,使用char格式,加索引,唯一且不為nil |
| name | varchar(12) | 昵稱(chēng) | 唯一 |
| desc | varchar(100) | 個(gè)人簡(jiǎn)介 | 簡(jiǎn)介 |
| sex | tinyint(1) | 性別 | 性別,1=man,2=woman,使用tinyint格式,默認(rèn)為0未知 |
| age | int | 年齡 | 用戶(hù)年齡,存儲(chǔ)的是時(shí)間戳,注意要用int64,因?yàn)閒lutter只有13位的時(shí)間戳 |
| avator | varchar(255) | 頭像 | 頭像 |
| follow_num | int | 關(guān)注數(shù) | 用戶(hù)關(guān)注他人的數(shù)量 |
| fans_num | int | 粉絲數(shù) | 用戶(hù)的粉絲數(shù) |
| state | tinyint(1) | 狀態(tài) | 用戶(hù)狀態(tài),比如=1賬號(hào)凍結(jié),=2不允許聊天之類(lèi)的,默認(rèn)=0 |
| weixin_openid | varchar | 微信授權(quán)用戶(hù)唯一標(biāo)示 | 唯一 |
| weixin_unionid | varchar | 微信授權(quán)用戶(hù)唯一標(biāo)示 | 唯一 |
| qq_openid | varchar | QQ授權(quán)用戶(hù)唯一標(biāo)示 | 唯一 |
那么結(jié)構(gòu)體User的格式如下:
package models
import (
"database/sql"
"github.com/jinzhu/gorm"
)
type User struct {
gorm.Model //會(huì)自動(dòng)添加id,created_at,updated_at,deleted_at四個(gè)字段,可以進(jìn)入看下類(lèi)型
Mobile string `gorm:"type:char(11);index;unique;not null;" json:"mobile,omitempty"` //手機(jī)號(hào),加索引,唯一,不為空
Name string `gorm:"type:varchar(12);"` //用戶(hù)昵稱(chēng),3-12個(gè)字符
Desc string `gorm:"type:varchar(100);"`
Sex int `gorm:"type:tinyint(1);default:0;"`
Age string `gorm:"type:char(13);"` //用戶(hù)年齡,存儲(chǔ)的是時(shí)間戳字符串
Avatar string `gorm:"type:varchar(255);"`
FollowNum int `gorm:"default:0;"`
FansNum int `gorm:"default:0;"`
State int `gorm:"type:tinyint(1);default:0;" json:"-"` //用戶(hù)狀態(tài),比如=1賬號(hào)凍結(jié),=2不允許聊天之類(lèi)的,默認(rèn)=0,為json時(shí)不返回
WeixinOpenid sql.NullString `gorm:"unique;index;" json:"-"` //微信openeid,唯一,加索引,json不返回,注意類(lèi)型使用sql.NullString。因?yàn)樵O(shè)置了唯一,而string默認(rèn)為"",所以會(huì)有沖突,一下同理
WeixinUnionid sql.NullString `gorm:"unique;" json:"-"` //微信unionid,唯一,json不返回
QqOpenid sql.NullString `gorm:"unique;index;" json:"-"` //QQopenid,唯一,加索引,json不返回
}
可以對(duì)應(yīng)上面的表格,看下gorm是如何定義的。
注釋中也有詳細(xì)的解釋?zhuān)⒁饪聪拢热鐬槭裁从胹ql.NullString類(lèi)型。
最后重新執(zhí)行run命令
