第一个 Gin 应用

环境准备好了,现在来写一个能实际运行的 Web 服务。我们会实现一个简单的用户管理 API。

最简示例

先从最简单的开始,只需要几行代码:

package main

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

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

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

    r.Run(":8080")
}

运行后访问 http://localhost:8080/,你会看到:

{
    "message": "Hello, Gin!"
}

代码解析

让我们逐行看看这段代码做了什么。

gin.Default()

r := gin.Default()

这行代码创建了一个 Gin 引擎。Default() 会自动添加两个中间件:

  • Logger:记录请求日志
  • Recovery:捕获 panic 并返回 500 错误

如果你不需要这些中间件,可以用 gin.New()

r := gin.New()

定义路由

r.GET("/", func(c *gin.Context) {
    // 处理逻辑
})

这里定义了一个 GET 请求的路由。"/" 是路径,后面是处理函数。

Gin 支持所有 HTTP 方法:

r.GET("/users", getUsers)
r.POST("/users", createUser)
r.PUT("/users/:id", updateUser)
r.DELETE("/users/:id", deleteUser)
r.PATCH("/users/:id", patchUser)

返回 JSON

c.JSON(200, gin.H{
    "message": "Hello, Gin!",
})

c.JSON() 返回 JSON 格式的响应。第一个参数是状态码,第二个是数据。

gin.H 是一个快捷方式,等价于 map[string]interface{}

启动服务

r.Run(":8080")

启动 HTTP 服务器,监听 8080 端口。如果不指定端口,默认是 8080。

完整示例:用户管理 API

下面是一个稍微完整一点的例子,实现了用户的增删改查:

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

type User struct {
    ID   string `json:"id"`
    Name string `json:"name"`
    Age  int    `json:"age"`
}

var users = []User{
    {ID: "1", Name: "Alice", Age: 25},
    {ID: "2", Name: "Bob", Age: 30},
}

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

    r.GET("/users", getUsers)
    r.GET("/users/:id", getUser)
    r.POST("/users", createUser)
    r.PUT("/users/:id", updateUser)
    r.DELETE("/users/:id", deleteUser)

    r.Run(":8080")
}

func getUsers(c *gin.Context) {
    c.JSON(http.StatusOK, users)
}

func getUser(c *gin.Context) {
    id := c.Param("id")

    for _, user := range users {
        if user.ID == id {
            c.JSON(http.StatusOK, user)
            return
        }
    }

    c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
}

func createUser(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    users = append(users, user)
    c.JSON(http.StatusCreated, user)
}

func updateUser(c *gin.Context) {
    id := c.Param("id")
    var updatedUser User

    if err := c.ShouldBindJSON(&updatedUser); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    for i, user := range users {
        if user.ID == id {
            users[i] = updatedUser
            users[i].ID = id
            c.JSON(http.StatusOK, users[i])
            return
        }
    }

    c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
}

func deleteUser(c *gin.Context) {
    id := c.Param("id")

    for i, user := range users {
        if user.ID == id {
            users = append(users[:i], users[i+1:]...)
            c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
            return
        }
    }

    c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
}

测试 API

可以用 curl 测试这些接口:

curl http://localhost:8080/users
curl http://localhost:8080/users/1
curl -X POST http://localhost:8080/users -d '{"id":"3","name":"Charlie","age":35}' -H "Content-Type: application/json"
curl -X PUT http://localhost:8080/users/1 -d '{"name":"Alice Updated","age":26}' -H "Content-Type: application/json"
curl -X DELETE http://localhost:8080/users/1

小结

这一章我们学习了:

  • 创建最简单的 Gin 应用
  • 理解 gin.Default() 和路由定义
  • 返回 JSON 响应
  • 实现一个完整的 CRUD API

现在你已经能用 Gin 写一个能用的 Web 服务了。