一、依赖管理
Go依赖管理演进
早期 Go 语言没有官方依赖管理工具,开发者常在项目中复制依赖包,导致更新困难、冲突处理复杂。社区因此推出了 Godep 和 glide 等第三方工具,它们管理 vendor 文件夹,记录依赖包版本,但仍存在全局依赖冲突和配置文件格式不统一的问题。 自 Go 1.11 起,Go 官方引入 Go Modules 作为依赖管理解决方案。它通过在项目中添加 go.mod 文件,明确指定依赖包及其版本,解决了全局依赖冲突,支持从代理服务器下载依赖包。Go Modules 不断发展和改进,支持私有仓库、替代模块和版本补丁,提供了更多强大功能。 总的来说,Go 语言的依赖管理经历了从手动复制到第三方工具再到官方 Go Modules 的演进,显著提高了依赖管理水平,提供了更好的开发者体验。
Go Module实践
Go Module 是自 Go 1.11 版本起引入的官方包管理工具,取代了原有的 GOPATH 和 vendor 目录。它将每个项目视为一个模块,拥有独立的模块路径,通过 go.mod 文件记录包依赖关系。
启用 Go Module 需满足以下条件:
-
Go 1.11 或更高版本
-
环境变量 GO111MODULE 需设置为 on
在项目中启用 Go Module 后,执行以下步骤进行包依赖管理:
-
go mod init 命令初始化新模块,如:go mod init myapp
-
go mod tidy 命令自动分析代码依赖,更新 go.mod 文件
-
go mod vendor 命令将依赖项复制到项目的 vendor 目录
此外,还有其他常用命令和功能:
-
go mod init: 初始化新模块
-
go get: 下载模块源代码,添加依赖
-
go list: 列出所有依赖项
-
go build / go run: 构建或运行项目
-
go mod edit: 手动编辑 go.mod 文件
-
go mod graph: 显示依赖关系图
-
go mod verify: 验证依赖项完整且未被篡改
Go Module 提供灵活且可靠的包管理方式,有助于更好地管理项目依赖关系,确保构建结果一致。它使 Go 语言包管理更现代化,受到开发者广泛欢迎。
二、测试
单元测试
Go 语言,一种实力和受欢迎程度兼备的编程语言,支持测试驱动开发(TDD)。在 Go 中,编写单元测试易如反掌。下面,我将向你展示如何用 Go 编写出色的单元测试。 首先,了解 Go 语言的测试工具。Go 自带一个名为 testing 的测试框架,提供了编写和执行测试所需的函数和工具。测试文件只需以_test.go 作为后缀,Go 编译器便会识别其为测试文件。 接着,来看一个简易示例。假设我们想要编写一个向数据库插入用户的函数 AddUser,以下是该函数及其对应测试的一个简洁示例:
// user_test.go
package module
import (
"fmt"
"testing"
)
func TestAddUser(t *testing.T) {
fmt.Println("测试用户:")
user:=&User{}
user.AddUser()
}
// user.go
package module
import (
"fmt"
"project/web/utils"
)
type User struct {
id int
username int
password string
}
func(user *User) AddUser() error{
sqlStr:="insert into `table`(user,password) values(?,?) "
//执行
_,err:=utils.Db.Exec(sqlStr,2,"ddddd")
if(err!=nil) {
fmt.Println("执行异常:",err)
return err
}
return nil
}
在上面的示例中,我们首先编写了一个向数据库插入用户的AddUser函数。然后,在user_test.go文件中,我们编写了一个名为TestAddUser的测试函数。
接下来,我们需要执行测试。可以通过在终端中运行以下命令来执行所有的单元测试:
go test
Go 语言自带的测试框架会自动识别并以_test.go 结尾的文件,执行其中的测试函数。测试结果会在终端展示,所有测试通过时,会显示通过的信息。
Go 语言还提供了一些额外的工具和函数,使我们能够编写更复杂和全面的单元测试。例如,我们可以使用 Skip 函数跳过特定的测试,或者使用 Table Driven Tests 功能来简化输入/输出测试的编写。
总的来说,Go 语言的单元测试直观易用,而且测试框架提供了丰富的功能和工具。通过编写有效的单元测试,我们可以保证代码的正确性,提高代码质量,减少后续开发和维护过程中的问题。希望这篇文章能帮助你开始使用 Go 语言的单元测试。祝你编写出更健壮的代码!
三、Gin
Gin框架导包"github.com/gin-gonic/gin"
Gin的使用
自定义拦截器
// 自定义拦截器
func myHandler() gin.HandlerFunc {
return func(context *gin.Context) {
context.Set("usersession", "userid-1")
context.Next()
context.Abort()
}
}
// 传参方式 url?userid=xxx&password=xxxxx 加了中间件
// myHandler() 没有指定则全部一起用
ginServer.GET("/user/info", myHandler(), func(context *gin.Context) {
// 取出中间件值
usersession := context.MustGet("usersession").(string)
log.Println("--------------", usersession)
userid := context.Query("userid")
password := context.Query("password")
context.JSON(http.StatusOK, gin.H{"userid": userid, "password": password})
})
设置图标
导包"github.com/thinkerou/favicon"
代码ginServer.Use(favicon.New("./u=G.jpg"))
Restful Api
//javascript代码
//gin restful API
ginServer.PUT("htllo", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "hello,world"})
})
ginServer.DELETE("/htllo")
页面加载响应
//加载静态页面
ginServer.LoadHTMLGlob("templates/*")
//响应一个页面给前端
ginServer.GET("/index", func(context *gin.Context) {
context.HTML(http.StatusOK, "index.html", gin.H{"msg": "hello,world"})
})
传参方式url?userid=xxx&password=xxxxx
//传参方式url?userid=xxx&password=xxxxx
ginServer.GET("/user/info", func(context *gin.Context) {
userid := context.Query("userid")
password := context.Query("password")
context.JSON(http.StatusOK, gin.H{"userid": userid,
"password": password})
})
传参方式user/info/1/kuangshen
//user/info/1/kuangshen
ginServer.GET("/user/info/:userid/:username", func(context *gin.Context) {
userid := context.Param("userid")
username := context.Param("username")
context.JSON(http.StatusOK, gin.H{"userid": userid, "username": username})
})
前端给后端传json
//前端给后端传json
ginServer.POST("/json", func(context *gin.Context) {
data, _ := context.GetRawData()
var m map[string]interface{}
_ = json.Unmarshal(data, &m)
context.JSON(http.StatusOK, m)
})
接收form表单
//接收form表单
ginServer.POST("/sdsd", func(context *gin.Context) {
username := context.PostForm("username")
password := context.PostForm("password")
context.JSON(http.StatusOK, gin.H{"username": username, "password": password})
})
路由
//路由
ginServer.GET("test", func(context *gin.Context) {
context.Redirect(http.StatusMovedPermanently, "https://www.baidu.com")
})
自定义404页面
//404
ginServer.NoRoute(func(context *gin.Context) {
context.HTML(http.StatusNotFound, "404.html", nil)
})
设置路由组
//路由组
userGroup := ginServer.Group("/user")
{
userGroup.GET("/add")
userGroup.POST("/login")
userGroup.POST("/logout")
}
启动
ginServer.Run(":8080")