这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天
进入初步实现了极速版抖音的登录注册功能
登录注册功能
项目结构
├─.idea
├─controller
├─dao
├─database
├─main
├─model
├─router
├─service
├─test
└─utils
![[Pasted image 20230119233412.png]]
由上面可知,基本的结构主要就是由路由层(router),控制层(controller),服务层(service),数据访问层(dao),数据模型层(model)构成。 在这里与原本JAVA后端的区别是,service层就直接实现具体业务代码,JAVA中还有Impl层
数据库代码
db_douyin/tb_user
CREATE TABLE users (
user_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户唯一标识', -- 用户id, 主键, 自增
username VARCHAR(255) NOT NULL COMMENT '用户名', -- 用户名, 唯一键
password VARCHAR(255) NOT NULL COMMENT '密码', -- 密码
follow_count BIGINT UNSIGNED DEFAULT 0 COMMENT '用户关注总数', -- 用户关注总数
follower_count BIGINT UNSIGNED DEFAULT 0 COMMENT '用户粉丝总数', -- 用户粉丝总数
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '用户注册时间', -- 用户注册时间
PRIMARY KEY (user_id),
UNIQUE KEY (username) -- 保证用户名唯一
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储用户信息';
代码
database/mysql.go
连接数据库,这里可以当成是数据库的配置之类的,以"数据库账户:数据库密码@(IP地址:端口号)/数据库名?timeout=10s&readTimeout=30s&writeTimeout=60s"的形式填入自己对应的数据。 此处定义了一个全局变量以及一个初始化数据库的函数,注意在main函数需要初始化一次数据库,即调用database.SqlClient(),否则数据库就不能用
model/user.go
这里是数据模型层,这里可以先在数据库定义好结构,然后用XO工具生成model层的数据,注意这里实体类的变量首字母要大写,否则会不成功;这里还有一个函数是用来返回表名的。func (u *User) TableName() string即为User类返回string类型的意思 补充: 数据库设计部分规范 【强制】id类型没有特殊要求,必须使用bigint unsigned,禁止使用int,即使现在的数据量很小。id如果是数字类型的话,必须是8个字节。 【推荐】字段尽量设置为 NOT NULL, 为字段提供默认值。 如字符型的默认值为一个空字符值串’’;数值型默认值为数值 0;逻辑型的默认值为数值 0; 【推荐】每个字段和表必须提供清晰的注释 【推荐】时间统一格式:‘YYYY-MM-DD HH:MM:SS’ 【强制】表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint ( 1表示是,0表示否)。 说明:任何字段如果为非负数,必须是 unsigned。 正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。 【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库 名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。 正例:health_user,rdc_config,level3_name 反例:HealthUser,rdcConfig,level_3_name 【强制】表名不使用复数名词。 说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数 形式,符合表达习惯。
package model
import (
"database/sql"
"time")
// 实体类
type User struct {
UserID uint64 `json:"user_id"` // user_id
Username string `json:"username"` // username
Password string `json:"password"` // password
FollowCount sql.NullInt64 `json:"follow_count"` // follow_count
FollowerCount sql.NullInt64 `json:"follower_count"` // follower_count
CreateTime time.Time `json:"create_time"` // create_time
}
// 表名
func (u *User) TableName() string {
return "tb_users"
}
dao/userMapper.go
数据访问层(dao),这里是与数据库连接的,相当于JAVA注解或者XML写的sql语句,这里还是直接理解成一个类即可,需要有初始化函数NewUserMapper(),下面是基本增删查改的格式 补充 常用gorm操作
service/userService.go
服务层(service),注意这里初始化的同时,还初始化了mapper的,而且定义结构的时候,也多写了一个userMapper(可以理解成JAVA的注解另一个层),这里是直接写业务逻辑的
controller/userController.go
控制层,这里后面可以换成统一格式返回,c.BindJSON(&user)可以直接当成是绑定POST请求过来的数据,与实体类一一对应,这里的注意同上
router/router.go
路由层,以以下的格式进行,注意这里还需要将controller初始化一次,然后以Group的形式定义分组路由
package router
import (
"github.com/gin-gonic/gin"
"go_douyin/controller")
func SetupRouter() *gin.Engine {
router := gin.Default()
userController := controller.NewUserController()
v1 := router.Group("/douyin/user")
{
v1.POST("register", userController.Register)
v1.POST("login", userController.Login)
}
return router
}
main.go
这里是运行的主函数,需要初始化数据库和初始化一下路由(让路由生效),以及定义一下端口
package main
import (
"go_douyin/database"
"go_douyin/router")
func main() {
// 注意初始化数据库
database.SqlClient()
r := router.SetupRouter()
r.Run(":8081")
}