Go 语言的依赖管理
Go 依赖管理演进经历了三个阶段:
- 早期 GOPATH:GOPATH 是一个环境变量,用来表明你写的 Go 项目的存放路径,所有的项目代码都放到 GOPATH 的 src 目录下。缓存文件会被保存在 $GOPATH/pkg 下。
- 中期 Go Vendor:在项目目录下增加 vender 文件,在 vender 存放了所有依赖包的副本。
- 最新 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 框架实战
需求描述
- 支持发布话题和回帖
- 生成ID保证不重复、唯一性
- 更新索引
实现思路
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
}