返回

文章详情

构建Gin:简单胜于容易

Hacker News2026年7月1日 17:45

2014年,我从旧金山回国,毫无计划,却带回了一个有用的伤疤:我看到小型软件团队对工具的需求。我在Joypad和TinySpark用了整整一年时间构建SDK,之后发布了我的第一个游戏。然后我回到西班牙,准备开始电信工程专业,并试图决定接下来要构建什么。答案是Fyve,一个围绕人们兴趣建立的社交网络。我选择Go作为后端,因为这个语言在合适的方面显得简单。Gin开始作为那个产品的Web框架,是我在学习Go的同时编写的,也当时我还在决定自己想成为怎样的工程师。代码存放在gin-gonic/gin。Fyve逐渐淡出,Gin却继续发展。简单胜于容易 那时,Go的Web框架人们不断向我推荐Martini。我立刻理解了原因。README文件小巧,中间件模型显得优雅,你可以在几分钟内让路由响应。Martini使用基于反射的依赖注入将处理程序连接起来。这让第一版演示变得流畅。但它也将重要的行为隐藏起来。服务通过魔法出现在处理程序中,控制流变得难以追踪,而反射在请求路径上运行。我当时正透过Rob Pike的《简单是复杂的》这本书来看Go社区。让我记住的不是关于极简主义的口号,而是成本模型:简单的软件通常需要构建它的人花费更多的工作,以便为使用它的人减少工作量。这成为Gin的设计理念。容易是第一个例子中看起来好的东西:更少的代码行,更优雅的语法,更少的仪式感。简单是更低的数量:更少的活动部分,更少的概念需要学习,更少的例外需要记忆。Martini让第一个版本变得容易。我希望Gin在代码库足够成熟以至于能够让我感到惊讶后,依然保持简单。寻找中间地带 亚里士多德的美德版本是中间地带:不要过多,也不要过少。这也是框架问题的形状。Martini给你太多魔法。Go的标准net/http给你提供了Web编程的真实版本:没有魔法,明确的控制流,以及你可以记住的处理程序形状。但它提供的帮助又太少。你在每个处理程序中写相同的路由参数、请求解析、验证和响应的管道。没有哪一部分是困难的,但足够多的内容就会变成噪音。Gin是我试图在它们之间找到有用的点:保持请求路径明确,不在此处运行反射,并把乏味的工作隐藏在一个你可以检查的对象后面:Context。r := gin.Default() r.GET("/users/:id", func(c *gin.Context) { id := c.Param("id") // 路径参数,无需反射 c.JSON(200, gin.H{"id": id}) // 响应渲染,单一调用 }) r.Run(":8080") 这个*gin.Context携带了请求、响应写入器、路径参数、验证助手和渲染。你只需传递一个对象。显而易见的操作只需一次方法调用,而机制可见性足够,便于在生产出现问题时进行调试。有趣的是,gin.Context在2014年发布,比Go的标准库中出现的context.Context早了两年。当它发布时,我们没有重命名我们的版本——我们让gin.Context满足标准接口,实现了完全兼容,没有一次破坏性更改。这是SDK工作的产品感在Web框架中的体现。当开发者体验让快速路径感觉自然时,那就是一个特性。 基于基数树构建的路由器 路由器是简单性原则变得具体的地方。Martini可以遍历正则表达式列表,并询问每个表达式是否匹配。这是灵活的。你可以让一个路由只能匹配数字,或者在模式内部隐藏额外的规则。但这也是框架内部的另一种语言。Gin选择了一种较小的路由语言:静态段、命名参数和兜底参数。这一选择使得路由器更快,因为它可以使用基数树,这也是httprouter在Go中流行的方法。更重要的是,它使得路由更容易推理。框架推动你走向常规路径,而不是巧妙的匹配器。 路由查找,不用扫描路由 routes 0 nodes 1 matched / 图。 一个压缩的基数树,实时构建和匹配。共享前缀合并为一条路径,然后/blog/42/comments遍历树并绑定42为:slug。 从普通路由开始 路由器看到路由字符串,如/search、/support和/blog/:slug/comments。一个天真的路由器可以逐个测试它们。基数树将共享文本转换为结构。共享前缀合并/search和/support,使用/s共享。两个博客路由共享/blog/,然后是:slug。每个共享的前缀只存储一次。匹配沿着一条路径进行 对于/blog/42/comments,查找遵循/blog/,将42绑定为:slug,然后继续到/comments。它不会扫描每个路由。热路径依然很小 工作随URL长度而变化。参数放入小切片中,匹配的处理程序已经就位。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡