青训营大项目心得一 | 青训营笔记

74 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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")  
}