大项目整理 | 青训营笔记

111 阅读2分钟

大项目整理 | 青训营笔记

这是我参与「第五届青训营」笔记创作活动的第17天。

protobuf 使用

protobuf 是一种 IDL,我们可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。

因为我在项目中主要负责评论方面的任务,所以下面主要介绍这部分逻辑,这部分代码主要实现两个功能:登录用户对视频进行评论;查看视频的所有评论,按发布时间倒序。

可以设定 protobuf :

syntax = "proto2";
package douyin.extra.first;

option go_package = "pb_comment/";

message douyin_comment_action_request {
  required string token = 1; // 用户鉴权token
  required int64 video_id = 2; // 视频id
  required int32 action_type = 3; // 1-发布评论,2-删除评论
  optional string comment_text = 4; // 用户填写的评论内容,在action_type=1的时候使用
  optional int64 comment_id = 5; // 要删除的评论id,在action_type=2的时候使用
}

message douyin_comment_action_response {
  required int32 status_code = 1; // 状态码,0-成功,其他值-失败
  optional string status_msg = 2; // 返回状态描述
  optional Comment comment = 3; // 评论成功返回评论内容,不需要重新拉取整个列表
}

message Comment {
  required int64 id = 1; // 视频评论id
  required User user =2; // 评论用户信息
  required string content = 3; // 评论内容
  required string create_date = 4; // 评论发布日期,格式 mm-dd
}

message User {
  required int64 id = 1; // 用户id
  required string name = 2; // 用户名称
  optional int64 follow_count = 3; // 关注总数
  optional int64 follower_count = 4; // 粉丝总数
  required bool is_follow = 5; // true-已关注,false-未关注
}
syntax = "proto2";
package douyin.extra.first;

option go_package = "pb_commentlist/";

message douyin_comment_list_request {
  required string token = 1; // 用户鉴权token
  required int64 video_id = 2; // 视频id
}

message douyin_comment_list_response {
  required int32 status_code = 1; // 状态码,0-成功,其他值-失败
  optional string status_msg = 2; // 返回状态描述
  repeated Comment comment_list = 3; // 评论列表
}

message Comment {
  required int64 id = 1; // 视频评论id
  required User user =2; // 评论用户信息
  required string content = 3; // 评论内容
  required string create_date = 4; // 评论发布日期,格式 mm-dd
}

message User {
  required int64 id = 1; // 用户id
  required string name = 2; // 用户名称
  optional int64 follow_count = 3; // 关注总数
  optional int64 follower_count = 4; // 粉丝总数
  required bool is_follow = 5; // true-已关注,false-未关注
}

然后进入目录:xx/idl,输入命令:protoc idl/{name}.proto --go_out=./idl

然后proto可以自动生成 xx.pb.go 文件,我们就可以直接使用 proto 规定好的 request 和 respose。

gorm 使用

gorm 可以把它看成 java 中的 mybatis-plus,它可以很方便的封装数据库的相关操作,下面介绍一段遍历评论列表并且按照时间顺序倒序返回的代码:

func FindComment(videoID int64) ([]Comment, error) {
	var comments []Comment
	// select * from comments where video_id = ? order by comment_time desc
	res := db.Where("video_id = ? ", videoID).Order("comment_time desc").Find(&comments)
	if res.Error != nil {
		logs.Error("查询comment表主键出错, err: ", res.Error)
		return nil, res.Error
	}
	var commentss []Comment
	for i := 0; i < int(res.RowsAffected); i++ {
		commentss = append(commentss, comments[i])
	}
	return commentss, nil
}

从上面的代码里我们可以看到 gorm 还是非常方便的,它可以很方便的通过 db.Select().Where().Find() 或者更加复杂的结构,就可以构建出各种各样的 mysql 操作。

herz 使用

Herz 类似于 gin 框架,不过它还有自己的一些优势,我在之前的笔记也介绍过 Herz 的相关背景之知识。

比如还是实现获取评论列表的代码逻辑:

type CommentListResponse struct {
	StatusCode  int32           `json:"status_code"`
	StatusMsg   string          `json:"status_msg,omitempty"`
	CommentList []model.Comment `json:"comment_list,omitempty"`
}

// 查看视频的所有评论,按发布时间倒序
func CommentList(ctx context.Context, c *app.RequestContext) {
	path := c.Request.Path()
	logs.Info("req path: %s", string(path))

	model.InitDB()

	// token := c.Query("token")
	video_id := c.Query("video_id")
	list, err := model.FindComment(video_id)
	if err != nil {
		c.String(http.StatusBadRequest, err.Error())
		return
	}
	resp := new(CommentListResponse)
	resp.StatusCode = 0
	resp.StatusMsg = "Success"
	resp.CommentList = list
	c.JSON(http.StatusOK, resp)
}

后续

在写好整体的代码逻辑之后,我们还需要进行进一步的测试,我们需要在 rounter 文件中注册自己的请求,然后在 main 函数里设置 ip 和端口号即可,比如我这里就在本地进行测试,

image.png

然后起服务之后,可以进行请求的发送,然后就可以得到

image.png

我们写在远程数据库中的值。

参考资料

gorm 官网

Herz 官网