这是我参与「第五届青训营 」伴学笔记创作活动的第 16 篇 本次笔记将记录大项目的答辩文档
1108组青训营后端结业项目答辩汇报文档
一、项目介绍
利用Golang实现极简版抖音的服务端
项目服务地址:本地服务
Github 地址:Github地址
二、项目分工
| 团队成员 | 主要贡献 |
|---|---|
| 田鹏飞 | 负责数据库设计、互动接口(及社交接口中的关注操作)、中间件的开发与配置、文档撰写 |
| 赵宇轩 | 负责后端架构设计、基础接口、Redis缓存的开发与配置、演示视频剪辑 |
三、项目实现
3.1 技术选型与相关开发文档
3.1.1数据库的选择与设计
数据库选择的是MySQL,对数据库操作的时候不是使用的Golang自带的sql包,而是使用的gorm。
用户表
type User struct { ID int64 `json:"id"` // 用户id UserName string `json:"user_name"` // 用户名 Password string `json:"password"` // 用户密码 CreatedAt time.Time `json:"created-at"` // 用户创建时间 UpdatedAt time.Time `json:"update_at"` // 用户上次更新用户数据的时间 } func (User) TableName() string { return "users" }用户详情表,在实际的开发中由于注册时没有详细信息的设置,但是在Feed、用户信息等接口需要获取取这些数据,这里就只是将表建立起来,在注册账户时会同步插入一个userName。
type UserInfo struct { ID int64 `json:"id"` // 用户id UserName string `json:"name"` // 用户名称 Avatar string `json:"avatar"` // 用户头像 BackgroundImage string `json:"background_image"` // 用户个人页顶部大图 Signature string `json:"signature"` // 个人简介 CreatedAt time.Time `json:"created-at"` // 用户创建时间 UpdatedAt time.Time `json:"update_at"` // 用户上次更新用户数据的时间 } func (UserInfo) TableName() string { return "user_info" }视频表
type Video struct { ID int64 `json:"id"` // 视频唯一标识 UserId int64 `json:"user_id"` // 作者id Title string `json:"title"` // 视频标题 PlayURL string `json:"play_url"` // 视频播放地址 CoverURL string `json:"cover_url"` // 视频封面地址 //FavoriteCount int64 `json:"favorite_count"` // 视频的点赞总数 //CommentCount int64 `json:"comment_count"` // 视频的评论总数 CreatedAt time.Time `json:"created-at"` // 视频发布时间 } func (Video) TableName() string { return "videos" }关注表
type Follow struct { ID int64 UserId int64 //关注者 FollowId int64 //被关注者 CreatedAt time.Time } func (Follow) TableName() string { return "follow" }评论表
type Comment struct { ID int64 VideoId int64 UserId int64 Context string CreatedAt time.Time } func (Comment) TableName() string { return "comment" }喜欢表
type Favorite struct { ID int64 `json:"id"` UserID int64 `json:"user_id"` VideoUserID int64 `gorm:"video_user_id"` VideoID int64 `json:"video_id"` } func (Favorite) TableName() string { return "favorite" }
3.1.2 http框架的选择
毫无疑问,http框架选择的是我们在青训营学习的hertz框架。
3.2 架构设计
3.2.1架构设计图
3.2.2项目目录结构
├─bytedance_douyin
│ ├─.idea
│ ├─biz
│ │ ├─config
│ │ ├─dao
│ │ ├─handler
│ │ ├─middleware
│ │ ├─model
│ │ │ ├─entity
│ │ │ └─vo
│ │ ├─redis
│ │ ├─router
│ │ ├─server
│ │ └─utils
│ └─static
│ └─videos
│ ├─main.go
3.3 项目代码及实现接口介绍
3.3.1项目代码
见Github项目地址:项目地址GitHub点我
3.3.2项目接口介绍
见青训营抖音项目文档:青训营抖音项目介绍文档
四、测试结果
4.1 基础接口
/douyin/feed/ - 视频流接口
{
"status_code": 0,
"status_msg": "视频列表返回成功",
"next_time": 1677141884,
"video_list": [
{
"author": {
"id": 1,
"name": "123456",
"avatar": "",
"background_image": "",
"signature": "",
"created-at": "2023-02-22T21:50:54.934+08:00",
"update_at": "2023-02-22T21:50:54.934+08:00",
"is_follow": false,
"total_favorited": 0,
"work_count": 1,
"favorite_count": 0,
"follow_count": 0,
"follower_count": 0
},
"comment_count": 0,
"cover_url": "http://172.29.219.224:8888/static/videos/userId1/1test11677073864.jpg",
"favorite_count": 0,
"id": 1,
"is_favorite": false,
"play_url": "http://172.29.219.224:8888/static/videos/userId1/1test11677073864.mp4",
"title": "test1"
}
]
}
/douyin/user/register/ - 用户注册接口
/douyin/user/login/ - 用户登录接口
/douyin/user/ - 用户信息
/douyin/publish/action/ - 视频投稿
/douyin/publish/list/ - 发布列表
{
"status_code": 0,
"status_msg": "视频列表返回成功",
"next_time": 1677142399,
"video_list": [
{
"author": {
"id": 1,
"name": "123456",
"avatar": "",
"background_image": "",
"signature": "",
"created-at": "2023-02-22T21:50:54.934+08:00",
"update_at": "2023-02-22T21:50:54.934+08:00",
"is_follow": false,
"total_favorited": 0,
"work_count": 1,
"favorite_count": 0,
"follow_count": 0,
"follower_count": 0
},
"comment_count": 0,
"cover_url": "http://172.29.219.224:8888/static/videos/userId1/1test11677073864.jpg",
"favorite_count": 0,
"id": 1,
"is_favorite": false,
"play_url": "http://172.29.219.224:8888/static/videos/userId1/1test11677073864.mp4",
"title": "test1"
}
]
}
5.2 互动接口
/douyin/favorite/action/ - 赞操作
点赞
取消点赞
/douyin/favorite/list/ - 点赞列表
{
"status_code": 0,
"status_msg": "获取视频列表成功",
"next_time": 0,
"video_list": [
{
"author": {
"id": 1,
"name": "123456",
"avatar": "",
"background_image": "",
"signature": "",
"created-at": "2023-02-22T21:50:54.934+08:00",
"update_at": "2023-02-22T21:50:54.934+08:00",
"is_follow": false,
"total_favorited": 0,
"work_count": 1,
"favorite_count": 0,
"follow_count": 0,
"follower_count": 0
},
"comment_count": 0,
"cover_url": "http://172.29.219.224:8888/static/videos/userId1/1test11677073864.jpg",
"favorite_count": 0,
"id": 1,
"is_favorite": false,
"play_url": "http://172.29.219.224:8888/static/videos/userId1/1test11677073864.mp4",
"title": "test1"
}
]
}
/douyin/comment/action/ - 评论操作
评论
取消评论
/douyin/comment/list/ - 视频评论列表
{
"status_code": 0,
"status_msg": "返回评论列表成功",
"comment_list": [
{
"content": "1111",
"create_date": "02-23",
"id": 2,
"user": {
"id": 1,
"name": "123456",
"avatar": "",
"background_image": "",
"signature": "",
"created-at": "2023-02-22T21:50:54.934+08:00",
"update_at": "2023-02-22T21:50:54.934+08:00",
"is_follow": false,
"total_favorited": 0,
"work_count": 0,
"favorite_count": 0,
"follow_count": 0,
"follower_count": 0
}
}
]
}
5.3 社交接口
/douyin/relation/action/ - 关注操作
关注
取消关注
五、Demo 演示视频 (必填)
This content is only supported in a Feishu Docs
六、项目总结与反思
6.1目前仍存在的问题
像MySQL中dsn、ffmpeg的文件路径等都应该是写到配置文件里面的,但是在操作的过程中,通过打印测试发现配置数据是正常读取的,但是在进行功能测试时就会出现问题,一直找不到原因。
6.2已识别出的优化项
- 密码用MD5加密,由于MD5加密是不可逆的,避免后台的管理员能直接登录用户的账号,在MD5加密时,还设置了一个盐值,避免用户密码过于简单,可以用暴力匹配破解密码。
- 最开始我们对前端传入的数据在某些方面并没有进行验证,比如我们在注册时,发现app已经对密码位数进行了验证,就没有进行验证,但是后来发现可能有人恶意的向我们后端发送请求,去注册一些不合理的密码。
- 对于向前端返回的数据,如果有错误,我们不直接返回err.Error(),避免暴露后端的问题而是将其打印在日志中,在返回的Status.Msg中返回“操作失败”或者更为贴切场景的提示,对于错误时返回Status.Code,我们时想与前端程序员进行约定,返回不同的数字代表相对应得错误,并且将该错误对应得常树写到一个专门的Go文件中
- 对于点赞、关注等操作,使用了redis缓存来降低服务器的压力
6.3一些想说的话
这次的青训营我是和我舍友组的队,我们两个人都是刚接触Golang,在这个项目实现的过程中,我们遇到了很多问题,我们两个一起解决了一些,但是还有一部分没解决了。这是我第一次真正意义上进行团队开发,项目的分工也没有上面写的那样明确,我们两个人遇到了问题,都是一起合作探讨解决的,过程中我深刻感受到了合作开发带来的便利与配合时的困难,我想这也是青训营不允许单人组队的原因。最后很感谢字节跳动青训营这个项目,提供了这么一个平台和机会。