← 返回博客
go2026-09-12 20:29:302 分钟 · 654 2

Gin 入门:10 分钟跑通第一个 HTTP 服务

从零初始化一个 Gin 项目,写出第一个能跑的 HTTP 接口,搞懂路由、参数获取和 JSON 响应,再用 air 实现热重载。

#gin#go#Web框架

Gin 是 Go 生态里最常用的一层 Web 框架:把路由、参数解析、中间件串起来,不替你决定 ORM、配置、部署方式。这一篇带你从空目录走到第一个能返回 JSON 的接口,跑通之后后面七篇都是在它上面加东西。

环境要求 Go 1.22 以上。下面所有命令都能直接复制执行。

1. 初始化项目

新建目录并初始化模块,模块名用你自己的仓库路径,本地练习写 demo 也行:

mkdir gin-demo && cd gin-demo
go mod init demo
go get github.com/gin-gonic/gin@v1.10.0

go get 会把下面的依赖写进 go.mod。如果拉取慢,先设国内代理:go env -w GOPROXY=https://goproxy.cn,direct

2. 写第一个 handler

main.go

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()

    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })

    // 默认监听 :8080
    r.Run()
}

gin.Default() 返回一个带 Logger 和 Recovery 中间件的引擎,新手直接用它最省心。gin.Hmap[string]any 的缩写,用来快速拼 JSON。r.Run() 不填参数时监听 0.0.0.0:8080

跑起来:

go run main.go

另开一个终端验证:

curl http://127.0.0.1:8080/ping
# {"message":"pong"}

3. 拿到 URL 里的参数

真实接口几乎都要读路径参数和查询参数。Gin 用 c.Param 取路径段,用 c.Query 取问号后的字段:

r.GET("/users/:id", func(c *gin.Context) {
    id := c.Param("id")                       // 路径 /users/42 里的 42
    page := c.DefaultQuery("page", "1")       // /users/42?page=2,缺省给 "1"
    q := c.Query("q")                         // 没有就返回空串

    c.JSON(200, gin.H{
        "id":   id,
        "page": page,
        "q":    q,
    })
})

:id 是单段通配,遇到 / 就截止。要匹配一整段含斜杠的路径用 *action,比如 /files/*action 能吃掉 /files/a/b/c

4. 接收 JSON 请求体

写接口时前端一般 POST 一段 JSON。用结构体承接,再 ShouldBindJSON 解析:

type LoginReq struct {
    Username string `json:"username" binding:"required"`
    Password string `json:"password" binding:"required"`
}

r.POST("/login", func(c *gin.Context) {
    var req LoginReq
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, gin.H{"username": req.Username})
})

binding:"required" 让 Gin 在字段缺失时直接返回错误。这一块的完整校验规则放到第 2 篇细讲。

5. 路由分组

接口一多就需要统一前缀和中间件。用 Group 把一批路由归到 /api/v1 下:

v1 := r.Group("/api/v1")
{
    v1.GET("/articles", listArticles)
    v1.POST("/articles", createArticle)
}

花括号只是代码块,没有语法含义,纯粹让分组更醒目。

6. 热重载

每次改代码都 go run 太烦。装 air 监听文件变化自动重启:

go install github.com/air-verse/air@latest

在项目根目录建 .air.toml

[build]
  cmd = "go run main.go"
  bin = "tmp/main"
  include_ext = ["go", "html", "toml"]
  exclude_dir = ["tmp", "vendor"]

然后直接敲 air,改完代码保存就自动重启。

7. 推荐的目录雏形

单文件能跑通,但文章一多就会乱。先把结构立起来,后面第 5 篇会扩展成完整分层:

gin-demo/
├── main.go          # 启动入口
├── router/
│   └── router.go    # 路由注册
├── handler/
│   └── user.go      # 具体接口实现
└── go.mod

r.GET(...) 里的匿名函数抽到 handler/user.go,在 router.go 里注册,main 只负责装配。这样每加一个模块,改动都收敛在一两个文件里。

下一篇讲路由的四种方法、参数绑定的全部写法,以及 binding 标签能做哪些校验。

相关推荐

本文为原创文章,采用CC BY-NC-SA 4.0协议授权,转载请保留署名与原文链接。原文链接:https://www.wxbuluo.com/article/177