这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
Gin项目的设计与分层
Gin框架非常的快速和高效
但是笔者使用的是springboot框架
springboot的分层非常的明显和直接
所以笔者思考用gin框架分层
设计
三层MCV结构
参考文献
基于Gin+Gorm框架搭建MVC模式的Go语言企业级后端系统 - 掘金 (juejin.cn)
首先,导入依赖
// 引入gin框架
require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.8.2
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/ugorji/go/codec v1.2.8 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
然后开始分层
首先我想到的是
controller层
经过学习,我查询到controller层可以用gin框架的路由代替
于是,再go文件夹下面建立route文件夹,然后创建route.go
开始初始化路由
apiRouter := r.Group("/douyin")
apiRouter.POST("/user/register/", controller.Register)
apiRouter.POST("/user/login/", controller.Login)
apiRouter.GET("/user/", jwt.VerifyToken, controller.UserInfo)
apiRouter.GET("/feed/", controller.VideoStream)
apiRouter.POST("/publish/action/", controller.VideoPublish)
apiRouter.GET("/publish/list/", controller.VideoList)
就像这样的情况,这样的不同的url请求就会定向到了controller的函数中去
然后再go的文件夹下再出创建service层
service层
接受controller的处理,同时用于返回错误信息
比如上图所示
这里用于xxxservice用于处理数据
就像这样的情况
用于处理contorler的参数,同时返回给上层的error,上层的err再开始处理
model层
model层用于定义数据模型
Gorm是全特性的ORM框架,即对象关系映射,这样,就需要类似Java那样建立与数据库映射的类,在Go语言当中,我们称之为结构体。
定义实体与sql模型的映射,同时定义curd接口,用于service层的调用。
// User 对应数据库User表结构的结构体
type User struct {
Id int64 //主键
Name string //昵称
Password string //密码
}
同时sql语句如下
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户id,自增主键',
`name` varchar(255) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '用户密码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb3 COMMENT='用户表';
这样就对应上来
踩坑点
由于不会jwt,所以耗尽大量的时候学习了golang的jwt框架的,所以研究jwt的时间比较长
这里定义了中间件用于jwt框架的颁发token和校验token
如上图
同时再路由组添加相应的函数,用于校验token,如果token解析错误,那就直接返回false,和相应的json。
如果校验正确,直接进入下一步的next方法中
Config
这个层级用于定义相关的配置文件,比如数据库连接,redis的连接,一些相关的常数
// 初始化并返回数据链接
func Init() *gorm.DB {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:zhang134679@tcp(127.0.0.1:3306)/tiktok?charset=utf8mb4&parseTime=True&loc=Local"
//dsn := "tiktok:tiktok@tcp(47.115.218.216:3306)/tiktok?charset=utf8mb4&parseTime=True&loc=Local"
Db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
PrepareStmt: true, //缓存预编译语句
})
if err != nil {
panic(err)
return nil
}
println("连接成功")
return Db
}
上述代码定义了数据库的连接
const Secret = "this_is_a_secret_key"
jwt的私钥
main
启动项目
func main() {
//连接数据库
err :=dao.InitMySql()
if err !=nil{
panic(err)
}
//程序退出关闭数据库连接
defer dao.Close()
//绑定模型
dao.SqlSession.AutoMigrate(&entity.User{})
//注册路由
r :=routes.SetRouter()
//
r.Run(":8080")
}
总结
gin也可以像springboot那样分层
只不过要自己定义的比较多
但是好在数据比较灵活