Go實(shí)戰(zhàn)項(xiàng)目【四】數(shù)據(jù)庫(kù)與構(gòu)建用戶(hù)模塊

這章開(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è)流程如下:


登錄注冊(cè)流程圖

根據(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

idcreate_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

user表

可以看到成功的創(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命令


image.png

點(diǎn)關(guān)注,不迷路

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容