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

68 阅读4分钟

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

1、统一返回格式

项目结构

├─.idea
├─controller
├─dao
├─database
├─global
├─main
├─model
├─router
├─service
├─test
└─utils
    └─response

实现统一的返回格式的步骤:

  1. 定义统一返回格式:为了统一返回格式,您需要定义一个结构体,包括需要返回的数据(例如视频列表)、状态码和错误消息。
  2. 实现返回函数:您可以实现一个函数,该函数接收需要返回的数据、状态码和错误消息,并返回统一的返回格式。
  3. 使用返回函数:在您的应用的各个路由和控制器中使用返回函数,以确保统一的返回格式。
goCopy code
type Response struct {
    Data    interface{} `json:"data"`
    Status  int         `json:"status"`
    Message string      `json:"message"`
}

func ResponseWithData(data interface{}, status int, message string) *Response {
    return &Response{
        Data:    data,
        Status:  status,
        Message: message,
    }
}

func GetVideos(w http.ResponseWriter, r *http.Request) {
    videos, err := getVideosFromDB()
    if err != nil {
        res := ResponseWithData(nil, 500, err.Error())
        json.NewEncoder(w).Encode(res)
        return
    }

    res := ResponseWithData(videos, 200, "")
    json.NewEncoder(w).Encode(res)
}

上面的代码定义了统一的返回格式(Response结构体),并实现了一个ResponseWithData函数,用于生成返回的数据。在应用的GetVideos函数中,我们可以使用ResponseWithData函数来生成统一的返回格式,并使用json.NewEncoder将其写入http.ResponseWriter中返回给客户端。

在实际使用中,也可以根据需要扩展Response结构体,以包含更多的数据,例如分页信息等。我们可以使用更多的状态码,以便更好地表示操作结果,例如200表示成功,404表示找不到,500表示服务器错误等。

学习到了相关只知识后,我在项目中也将各个返回都统一了格式

使用统一的返回格式可以使您的代码更具可读性和可维护性,并使客户端更容易处理数据。

2、点赞和喜欢功能

  1. 建立数据模型:为点赞和喜欢功能建立一个数据模型,该模型包括用户ID、视频ID和点赞/喜欢状态(例如:点赞或未点赞)。使用数据库存储该数据。
  2. 实现点赞和喜欢路由:为点赞和喜欢功能创建一个路由,该路由根据用户的请求更新数据模型中的点赞/喜欢状态。
  3. 实现点赞和喜欢处理程序:实现一个处理程序,该处理程序接收用户的请求,更新数据模型中的点赞/喜欢状态,并返回结果。
  4. 实现视频列表路由:实现一个视频列表路由,该路由返回所有视频的详细信息,以及每个视频的点赞/喜欢状态。

使用联合主键避免重复点赞

CREATE TABLE tb_favorite ( 
user_id BIGINT UNSIGNED NOT NULL COMMENT '用户id', -- 用户id, 外键 
video_id BIGINT UNSIGNED NOT NULL COMMENT '视频id', -- 视频id, 外键 
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '点赞时间', -- 点赞时间 
PRIMARY KEY (user_id, video_id),
FOREIGN KEY (user_id) REFERENCES tb_users(user_id), 
FOREIGN KEY (video_id) REFERENCES tb_videos(video_id) -- 外键关联用户表和视频表
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储用户对视频的点赞状态';

部分相关代码:

go Copy code type Video struct { ID int json:"id" Title string json:"title" Liked bool json:"liked" } type Like struct { UserID int `json:"user_id”

`VideoID int`json:"video_id"`Liked bool`json:"liked"` }

// 实现点赞和喜欢路由 
func likeHandler(w http.ResponseWriter, r *http.Request) { 
// 解析请求数据 
var like Like err := json.NewDecoder(r.Body).Decode(&like) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return }

// 更新数据模型中的点赞/喜欢状态
updateLikeStatus(like)

// 返回结果 
w.WriteHeader(http.StatusOK) w.Write([]byte("点赞/喜欢操作成功完成")) }

// 实现视频列表路由
func videoListHandler(w http.ResponseWriter, r *http.Request) { 
// 获取所有视频的详细信息和点赞/喜欢状态 
videos := getVideoList()

// 将结果转换为JSON格式并返回 
result, err := json.Marshal(videos) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return }

w.WriteHeader(http.StatusOK) w.Write(result) }

// 启动服务器 
func main() { http.HandleFunc("/like", likeHandler) http.HandleFunc("/videos", videoListHandler) err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal(err) } }

把“Like”结构体加入到数据库:

func (l *Like) AddLike() error { db := dbconn.GetDB() err := db.Create(l).Error if err != nil { return err } return nil }

更新点赞/喜欢状态:


func (l *Like) UpdateLike() error { db := dbconn.GetDB() err := db.Save(l).Error if err != nil { return err } return nil }
获取视频列表:

func GetVideos() ([]Video, error) { db := dbconn.GetDB() var videos []Video err := db.Find(&videos).Error if err != nil { return nil, err } for i, video := range videos { var count int db.Model(&Like{}).Where("video_id = ?", video.ID).Count(&count) videos[i].Liked = count > 0 } return videos, nil }