【Go项目实战案例】青训营话题帖子详细实现步骤 | 青训营笔记

116 阅读4分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 15 天,今天学习的内容是关于青训营话题帖子详细实现步骤,根据课程内容整理学习笔记如下。

Go语言项目实战

通过项目需求、需求拆解、逻辑设计、代码实现感受真实的项目开发

1 需求背景

需求模型来源

青训营话题页

image-20230116204550298.png

需求

  1. 实现一个展示话题(标题,文字描述)和回帖列表的后端http接口;
  2. 话题和回帖数据用本地文件存储
  3. 暂不考虑前端页面的实现,仅仅实现一个本地web服务

3.5.2 需求分析与项目规划

页面需要的实体为 - 话题与帖子

ER图

image-20230116205047875.png

分层结构

  • 数据层:数据Model,外部数据的增删改查
  • 逻辑层:业务Entity,处理核心业务逻辑输出
  • 视图层:视图View,处理和外部交互的逻辑

image-20230116205431362.png

组件及技术点

3 实现步骤

初始化go mod

创建文件夹,执行命令

 go mod init my-goproject

创建 go.mod 文件

image-20230116210704448.png

获取gin框架

下载gin框架

 go get -u github.com/gin-gonic/gin
 #go get -u gopkg.in/gin-gonic/gin.v1@v1.3.0

Tips:

如果使用第二个命令,会出现以下报错,原因是在使用 GOPROXY 的时候,开启了 GO111MODULE ,导致包管理非官方所说的在 $GOPATH\src,而是去了 $GOPATH\pkg 目录下

image-20230116212919096.png

直接使用 edit 命令编辑,再下载即可

 go mod edit -require gopkg.in/gin-gonic/gin.v1@v1.3.0
 go mod download

可以看到生成了 go.sum 文件,包导入成功

image-20230116213124424.png

Repository 数据层实现

我们从示例代码中拷贝 /data 数据文件夹,其中包含 topicpost 两个文件,存放话题与帖子的信息

image-20230116214306189.png

要实现的是对该话题与帖子信息的查询

image-20230116214018623.png

拷贝 /repository 代码文件夹,其中包含三个文件,数据库初始化以及话题与帖子的查询。

db_init.go 文件中,我们使用 map 将数据通过索引进行映射

image-20230116214553253.png

初始化话题数据索引: 打开对应的数据文件,通过迭代器的方式对数据行进行遍历,用 json.Unmarshal 将数据从json格式转换存储到结构体中

image-20230116215041067.png

根据话题数据索引进行查询:topic.go 文件中,我们根据话题ID作为索引进行话题数据查询

image-20230116215427484.png

Tips: sync.Once

参考文档:Go sync.Once

其中使用的 sync.Once 是Go标准库提供的使函数只执行一次的实现,常应用于高并发下只执行一次的场景,如单例模式。通常使用进行初始化配置、保持数据库连接等。其可以减少存储浪费,提高性能。

在多数情况下,sync.Once 被用于控制变量的初始化,这个变量的读写满足如下三个条件:

  • 当且仅当第一次访问某个变量时,进行初始化(写);
  • 变量初始化过程中,所有读都被阻塞,直到初始化完成;
  • 变量仅初始化一次,初始化完成后驻留在内存里。

sync.Once 仅提供了一个方法 Do,参数 f 是对象初始化函数。

 func (o *Once) Do(f func())

原理: 保证变量仅被初始化一次,需要有个标志来判断变量是否已初始化过,若没有则需要初始化;同时要保证线程安全,支持并发,需要互斥锁来实现。

然后,我们参考以上实现类似的帖子信息的索引与查询。

Service 逻辑层实现

拷贝 /server 代码文件夹,其中包含两个文件

image-20230116221052112.png

代码的实现按照以上三个流程

image-20230116221417414.png

准备数据部分,由于两部分信息不存在依赖,因此使用并行执行

image-20230116221606597.png

Tips:

其中要用到 assert 包中的等于不等于等方法

image-20230118113522355.png

我们需要下载并安装该包到依赖

 go get -u github.com/stretchr/testify/assert

补充get参数:

附加参数备 注
-v显示操作流程的日志及信息,方便检查错误
-u下载丢失的包,但不会更新已经存在的包
-d只下载,不安装
-insecure允许使用不安全的 HTTP 方式进行下载操作

image-20230118113634184.png

下载完成,查看 go.mod ,已经包含该依赖

image-20230118113732679.png

Controller 视图层实现

拷贝 /controller 代码文件夹,其中包含一个文件

在其中我们构建View对象以及定义业务错误码

Router

通过Gin搭建Web框架,拷贝代码文件 server.go ,其为一个函数入口,包名为 main ,放在根目录下。

  1. 初始化数据索引
  2. 初始化引擎配置
  3. 构建路由
  4. 启动服务

Tips: 注意在以上拷贝的代码文件中需要将项目文件的包名改成我们自己定义的包名。

image-20230118114554112.png

4 运行

运行gin框架

 go run server.go

开一个新终端,用 curl 命令进行访问,比如我们访问第二页

 curl http://127.0.0.1:8080/community/page/get/2

image-20230118121759402.png

可以看到此时成功查询并返回了结果。这样,一个基于Gin的简单后端框架就搭建完成了