問(wèn)答論壇網(wǎng)站建設(shè)網(wǎng)站怎么制作教程
目錄
- 文件結(jié)構(gòu)
- 數(shù)據(jù)庫(kù)準(zhǔn)備
- 配置文件處理
- config.go
- db_list.go
- gorm_mysql.go
- system.go
- 初始化數(shù)據(jù)庫(kù)
- gorm.go
- gorm_mysql.go
- 開始初始化
- 測(cè)試數(shù)據(jù)庫(kù)
- 定義實(shí)體類 User
- service
- api
- 開始測(cè)試!
文件結(jié)構(gòu)
本文章將使用到上一節(jié)創(chuàng)建的 CommonService 接口,用于測(cè)試連接數(shù)據(jù)庫(kù)狀況,當(dāng)然您也可以自制簡(jiǎn)單接口作為測(cè)試,不會(huì)影響整體工作流程!
下方樹狀圖為最終項(xiàng)目結(jié)構(gòu)
文件夾 api 與 service 助力數(shù)據(jù)庫(kù)查詢請(qǐng)求
initialize/gorm.go
初始化 GORM
initialize/gorm_mysql.go
執(zhí)行 MySQL 數(shù)據(jù)庫(kù)對(duì)應(yīng)的初始化過(guò)程
user.go
一個(gè)實(shí)體類
│ config.yaml
│ go.mod
│ go.sum
│ main.go
│
├─api
│ │ enter.go
│ │
│ ├─example
│ └─system
│ api_common.go
│ enter.go
│
├─config
│ config.go
│ db_list.go
│ gorm_mysql.go
│ jwt.go
│ local.go
│ system.go
│
├─core
│ constant.go
│ server.go
│ viper.go
│
├─global
│ global.go
│
├─initialize
│ │ gorm.go
│ │ gorm_mysql.go
│ │ router.go
│ │
│ └─internal
│ gorm.go
│
├─model
│ user.go
│
├─router
│ │ enter.go
│ │
│ ├─example
│ └─system
│ enter.go
│ sys_common.go
│
└─service
之后回到項(xiàng)目根目錄,打開命令行,輸入指令安裝 MySQL 驅(qū)動(dòng):
go get -u gorm.io/driver/mysql
數(shù)據(jù)庫(kù)準(zhǔn)備
這是我本地使用的數(shù)據(jù)庫(kù)參數(shù):
username:root
password:123456
dbname:golang
這是數(shù)據(jù)庫(kù)“golang”中的數(shù)據(jù)表 user 的數(shù)據(jù),注意到有四個(gè)屬性
來(lái)到 go 項(xiàng)目中,根據(jù)上述參數(shù),打開 config.yaml
,添加 mysql 配置
(這里為了便于大家操作,省去了源碼中的注冊(cè) zap 的部分)
同時(shí)添加 system
對(duì)象,內(nèi)含一個(gè) db-type
屬性,用來(lái)定義我們希望后端鏈接的數(shù)據(jù)庫(kù)類型
system:db-type: "mysql"mysql:path: "localhost"port: "3306"config: ""db-name: "golang"username: "root"password: "123456"max-idle-conns: 10max-open-conns: 100
配置文件處理
由于我們?yōu)?config.yaml 添加了新的配置項(xiàng),所以需要按照我們之前文章所屬,為其配置指定的結(jié)構(gòu)!
config.go
打開(如果你跟隨上上節(jié)文章)或者新建文件 config/config.go
在主 config 入口添加 mysql 屬性
type Server struct {...Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
}
db_list.go
新建文件 config/db_list.go
由于我們有可能需要支持多種類型的數(shù)據(jù)庫(kù)(比如 PostgreSQL),所以最佳解決辦法就是創(chuàng)建一個(gè)通用的數(shù)據(jù)庫(kù)參數(shù)結(jié)構(gòu)體
DSNProvider
接口用來(lái)給 GORM 提供 DSN
type DSNProvider interface {Dsn() string
}type GeneralDB struct {Path string `mapstructure:"path" json:"path" yaml:"path"` // 服務(wù)器地址:端口Port string `mapstructure:"port" json:"port" yaml:"port"` //:端口Config string `mapstructure:"config" json:"config" yaml:"config"` // 高級(jí)配置Dbname string `mapstructure:"db-name" json:"db-name" yaml:"db-name"` // 數(shù)據(jù)庫(kù)名Username string `mapstructure:"username" json:"username" yaml:"username"` // 數(shù)據(jù)庫(kù)用戶名Password string `mapstructure:"password" json:"password" yaml:"password"` // 數(shù)據(jù)庫(kù)密碼Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"` //全局表前綴,單獨(dú)定義TableName則不生效Singular bool `mapstructure:"singular" json:"singular" yaml:"singular"` //是否開啟全局禁用復(fù)數(shù),true表示開啟Engine string `mapstructure:"engine" json:"engine" yaml:"engine" default:"InnoDB"` //數(shù)據(jù)庫(kù)引擎,默認(rèn)InnoDBMaxIdleConns int `mapstructure:"max-idle-conns" json:"max-idle-conns" yaml:"max-idle-conns"` // 空閑中的最大連接數(shù)MaxOpenConns int `mapstructure:"max-open-conns" json:"max-open-conns" yaml:"max-open-conns"` // 打開到數(shù)據(jù)庫(kù)的最大連接數(shù)
}
gorm_mysql.go
新建文件 gorm_mysql.go
在這里定義 mysql 結(jié)構(gòu)體,直接使用通用數(shù)據(jù)庫(kù)參數(shù)結(jié)構(gòu)體 GeneralDB 即可
然后于此實(shí)現(xiàn)接口 DSNProvider
,構(gòu)造 DSN
type Mysql struct {GeneralDB `yaml:",inline" mapstructure:",squash"`
}func (m *Mysql) Dsn() string {return m.Username + ":" + m.Password + "@tcp(" + m.Path + ":" + m.Port + ")/" + m.Dbname + "?" + m.Config
}
system.go
打開文件 config/system.go
老樣子,為 db_type 配置對(duì)應(yīng)結(jié)構(gòu)體內(nèi)容
type System struct {DbType string `mapstructure:"db-type" json:"db-type" yaml:"db-type"`
}
初始化數(shù)據(jù)庫(kù)
gorm.go
新建文件 initialize/gorm.go
此處的邏輯很簡(jiǎn)單,即通過(guò)全局變量獲取 db_type 屬性,得知開發(fā)者想要用那種數(shù)據(jù)庫(kù);
由于我們只會(huì)用到 MySQL,故這里的判斷就都啟動(dòng) mysql 了
GormMysql
目前處于飄紅狀態(tài),因?yàn)檫€沒(méi)有定義,下面我們將為其定義初始化 MySQL 的方法
import ("ginlogin/global""gorm.io/gorm"
)func Gorm() *gorm.DB {switch global.G_CONFIG.System.DbType {case "mysql":return GormMysql()default:return GormMysql()}
}
gorm_mysql.go
新建文件 initialize/gorm_mysql.go
具體通過(guò) GORM 鏈接 mysql 的過(guò)程相信大家也很熟悉,這里就不多費(fèi)口舌了,直接看注釋吧!
import ("fmt""ginlogin/global""gorm.io/driver/mysql""gorm.io/gorm"
)// 初始化mysql方法,返回一個(gè)gorm.DB引用
func GormMysql() *gorm.DB {// 第一步// 全局變量獲取config中定義的mysql參數(shù)// 判斷如果不急于數(shù)據(jù)庫(kù)名,直接返回nil表示初始化數(shù)據(jù)庫(kù)失敗info := global.G_CONFIG.Mysqlif info.Dbname == "" {return nil}// 第二步// 構(gòu)造mysqlConfigmysqlConfig := mysql.Config{DSN: info.Dsn(),DefaultStringSize: 191,SkipInitializeWithVersion: false,}// 第三步// gorm.Open連接到數(shù)據(jù)庫(kù),并處理錯(cuò)誤if db, err := gorm.Open(mysql.New(mysqlConfig)); err != nil {fmt.Println("完蛋,連接不上數(shù)據(jù)庫(kù)!!!")return nil} else {// 如果成功鏈接,設(shè)置好連接池啥的,就可以返回db了db.InstanceSet("gorm:table_options", "ENGINE="+info.Engine)sqlDB, _ := db.DB()sqlDB.SetMaxIdleConns(info.MaxIdleConns)sqlDB.SetMaxOpenConns(info.MaxOpenConns)return db}
}
開始初始化
哎?這還沒(méi)完,你還要調(diào)用初始化方法!
打開 main.go,添加如下代碼,調(diào)用 GORM 初始化方法
func main() {// 初始化數(shù)據(jù)庫(kù)DBglobal.G_DB = initialize.Gorm()...
}
此處關(guān)于整合 mysql 的部分已經(jīng)完結(jié)了,下面將是測(cè)試數(shù)據(jù)庫(kù)的內(nèi)容,您可以直接略過(guò)
測(cè)試數(shù)據(jù)庫(kù)
定義實(shí)體類 User
新建文件 model/user.go
根據(jù)開頭所述 user 表,故可定義如下實(shí)體類
type User struct {Id int `json:"id"`Username string `json:"username"`Password string `json:"password"`Role int `json:"role"`
}// 顯式指定表名
func (User) TableName() string {return "user"
}
service
打開文件 service/system/service_common.go
service 層內(nèi)簡(jiǎn)單實(shí)現(xiàn)了查詢整張表的功能,并作了錯(cuò)誤處理
type CommonService struct{}func (s *CommonService) CreateApi(c *gin.Context) (err error) {// 調(diào)用Find方法查詢表,將查詢成功與否的結(jié)果存到res變量var userList []model.Userres := global.G_DB.Find(&userList)// 判斷res是否出現(xiàn)了錯(cuò)誤if errors.Is(res.Error, gorm.ErrRecordNotFound) {return errors.New("找不到這個(gè)元素")}// 如果沒(méi)錯(cuò),那就返回?cái)?shù)據(jù)c.JSON(http.StatusOK, gin.H{"data": userList,})// 給api層傳遞一個(gè)errorreturn res.Error
}
api
打開文件 api/system/api_common.go
很簡(jiǎn)單,調(diào)用 service,然后在 api
中處理錯(cuò)誤并返回 JSON
數(shù)據(jù)(這一步也可以直接全部寫在 service
層里,此時(shí)就可以把該 api 層看做是 springboot
中的 controller
層了!)
import ("github.com/gin-gonic/gin""net/http"
)type CommonApi struct{}func (s *CommonApi) CreateApi(c *gin.Context) {err := commonService.CreateApi(c)if err != nil {c.JSON(http.StatusBadRequest, gin.H{"status": err.Error(),})}
}
開始測(cè)試!
萬(wàn)事俱備,只欠東風(fēng),打開你的 postman|apifox|apipost,請(qǐng)求以下看看結(jié)果吧!