GO语言工程实践课后作业 | 青训营

58 阅读3分钟

Go 语言的依赖管理

Go 依赖管理演进经历了三个阶段:

  1. 早期 GOPATH:GOPATH 是一个环境变量,用来表明你写的 Go 项目的存放路径,所有的项目代码都放到 GOPATH 的 src 目录下。缓存文件会被保存在 $GOPATH/pkg 下。
  2. 中期 Go Vendor:在项目目录下增加 vender 文件,在 vender 存放了所有依赖包的副本。
  3. 最新 Go Module:目前被广泛应用的是 Go Module,整个演进路线主要围绕实现两个目标来迭代发展:在不同环境(项目)依赖的库的版本不同;控制并管理依赖库的版本。

其中 Go Module 是 Go 语言官方推荐的依赖管理工具,可以方便地解决依赖、版本控制和私有库的问题。要使用 Go Module,需要按照以下步骤操作:

在项目根目录执行go mod init命令,初始化 go.mod 文件,该文件包含了项目的 module 名称和版本信息。

在项目中使用 go get 命令获取第三方依赖库,例如go get example.com/some/package,该命令会自动将依赖库下载到本地。

在代码中使用 import 语句引入依赖库,例如import "example.com/some/package"

使用go mod tidy命令会自动将缺失的依赖库下载到本地,并解决冲突。

在使用依赖库时,可以通过go mod graph命令查看依赖图,了解每个依赖库的版本关系。

可以使用go mod vendor命令将依赖库下载到本地 vendor 目录,以避免在不同环境之间依赖库版本不一致的问题。

总之,Go Module 提供了方便的依赖管理工具,可以帮助开发者更好地管理项目中的依赖库和版本控制。

使用 Gin 框架实战

需求描述

  1. 支持发布话题和回帖
  2. 生成ID保证不重复、唯一性
  3. 更新索引

实现思路

1.获取数据 发布话题首先需要获取用户要发布的内容,如果是回复的话,还需要有回复话题的 ID 和回复内容。我在设置路由时,获取到了用户的输入,校验完数据后传给 controller 进行处理; 2.处理数据 获取完数据后,需要对数据进行封装处理,使其成为一个结构体,包含 ID,回复话题ID、话题内容、发布时间; 3.生成唯一ID 生成ID我是采用时间戳+随机数的方式实现的; 4.保存数据 将结构体序列化为JSON格式,追加到文件末尾,同时更新索引。若是发表话题,直接新增索引就可以;若是发表回复,需要先判断,当前话题有没有回复,没有的话需要新创建一个数组;

实现代码

在 server.go 定义了一个发布话题的路由,http://127.0.0.1:8080/api/publish/topic采用 POST 请求方法来接受用户输入的信息。因为没有实现前端,所以使用 postman 进行接口测试。接口功能初步满足预取设计需求。

r.POST("/api/publish/topic", func(context *gin.Context) {
title := context.PostForm("title")
content := context.PostForm("content")
data, err := cotroller.PublishTopic(title, content)
if err != nil {
  return
}
context.JSON(200, data)
})

获取到用户的数据后,我们先生成一个全局唯一的话题ID,再将获取到的话题信息封装进 repository.Topic 结构体中即可。

func PublishTopic(title string, content string) (topic repository.Topic, err error) {
  time := time.Now()
  id := time.Unix() + rand.Intn(100)
  timeFormat := time.Format("2023-01-01 15:00:00")
  topic, err = repository.NewTopicDaoInstance().CreateTopic(id, title, content, timeFormat)
  if err != nil {
    return topic, err
  }
  return topic, nil
}

封装数据的结构体

newTopic := Topic{
    Id: id,
    Title: title,
    Content: content,
    CreateTime: createTime,
    ReplyId: replyId,
}

由于没有对接数据库进行存储,这里就将结构体数据保存到文件当中随时读取。

//打开文件
f, err := os.OpenFile("./data/topic", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
    return newTopic, err
}
//在函数执行完之后关闭文件
defer f.Close()
//序列化
marshal, _ := json.Marshal(newTopic)
//写入文件
if _, err = f.WriteString(string(marshal) + "\n"); err != nil {
    return newTopic, err
}