第一个应用 #
一、Hello World #
1.1 创建项目 #
bash
# 创建项目目录
mkdir hello-gin
cd hello-gin
# 初始化模块
go mod init hello-gin
# 安装Gin
go get -u github.com/gin-gonic/gin
1.2 编写代码 #
创建 main.go 文件:
go
package main
import "github.com/gin-gonic/gin"
func main() {
// 创建默认路由引擎
r := gin.Default()
// 定义GET路由
r.GET("/", func(c *gin.Context) {
c.String(200, "Hello, Gin!")
})
// 启动HTTP服务,默认在0.0.0.0:8080启动服务
r.Run()
}
1.3 运行项目 #
bash
# 运行项目
go run main.go
# 输出
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
[GIN-debug] GET / --> main.main.func1 (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080
1.4 测试接口 #
bash
# 使用curl测试
curl http://localhost:8080/
# 输出
Hello, Gin!
二、代码解析 #
2.1 创建路由引擎 #
go
// 创建带有默认中间件的路由
r := gin.Default()
// 等价于
r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())
// 创建不带中间件的路由
r := gin.New()
2.2 定义路由 #
go
// GET请求
r.GET("/get", func(c *gin.Context) {
c.String(200, "GET request")
})
// POST请求
r.POST("/post", func(c *gin.Context) {
c.String(200, "POST request")
})
// PUT请求
r.PUT("/put", func(c *gin.Context) {
c.String(200, "PUT request")
})
// DELETE请求
r.DELETE("/delete", func(c *gin.Context) {
c.String(200, "DELETE request")
})
// PATCH请求
r.PATCH("/patch", func(c *gin.Context) {
c.String(200, "PATCH request")
})
// HEAD请求
r.HEAD("/head", func(c *gin.Context) {
c.String(200, "HEAD request")
})
// OPTIONS请求
r.OPTIONS("/options", func(c *gin.Context) {
c.String(200, "OPTIONS request")
})
// 匹配所有HTTP方法
r.Any("/any", func(c *gin.Context) {
c.String(200, "Any request")
})
2.3 处理函数 #
go
// 匿名函数
r.GET("/anonymous", func(c *gin.Context) {
c.String(200, "Anonymous function")
})
// 命名函数
func helloHandler(c *gin.Context) {
c.String(200, "Named function")
}
r.GET("/named", helloHandler)
// 方法绑定
type UserController struct{}
func (u *UserController) Hello(c *gin.Context) {
c.String(200, "Method handler")
}
user := &UserController{}
r.GET("/method", user.Hello)
2.4 启动服务器 #
go
// 默认端口8080
r.Run()
// 指定端口
r.Run(":3000")
// 指定地址和端口
r.Run("127.0.0.1:3000")
// 使用http.Server
r := gin.Default()
s := &http.Server{
Addr: ":8080",
Handler: r,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
三、Context上下文 #
3.1 Context简介 #
Context是Gin的核心,封装了请求和响应:
go
func handler(c *gin.Context) {
// c.Request - http.Request
// c.Writer - http.ResponseWriter
}
3.2 获取请求参数 #
go
r.GET("/query", func(c *gin.Context) {
// 获取查询参数
name := c.Query("name") // 获取name参数
name = c.DefaultQuery("name", "Guest") // 带默认值
// 获取所有查询参数
values := c.Request.URL.Query()
c.String(200, "Hello %s", name)
})
3.3 获取路径参数 #
go
// 获取路径参数
r.GET("/user/:id", func(c *gin.Context) {
id := c.Param("id")
c.String(200, "User ID: %s", id)
})
// 获取可选路径参数
r.GET("/user/:id/*action", func(c *gin.Context) {
id := c.Param("id")
action := c.Param("action")
c.String(200, "User ID: %s, Action: %s", id, action)
})
3.4 获取表单数据 #
go
r.POST("/form", func(c *gin.Context) {
// 获取表单数据
username := c.PostForm("username")
password := c.DefaultPostForm("password", "")
c.String(200, "Username: %s, Password: %s", username, password)
})
3.5 获取JSON数据 #
go
r.POST("/json", func(c *gin.Context) {
// 方式1:绑定到map
var json map[string]interface{}
if err := c.BindJSON(&json); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// 方式2:绑定到结构体
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"user": user})
})
四、响应处理 #
4.1 字符串响应 #
go
r.GET("/string", func(c *gin.Context) {
c.String(200, "Hello, World!")
})
// 格式化字符串
r.GET("/format", func(c *gin.Context) {
name := "Gin"
c.String(200, "Hello, %s!", name)
})
4.2 JSON响应 #
go
// 使用gin.H
r.GET("/json1", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "ok",
"status": 200,
})
})
// 使用结构体
r.GET("/json2", func(c *gin.Context) {
type Response struct {
Message string `json:"message"`
Status int `json:"status"`
}
c.JSON(200, Response{
Message: "ok",
Status: 200,
})
})
// 使用map
r.GET("/json3", func(c *gin.Context) {
c.JSON(200, map[string]interface{}{
"message": "ok",
"status": 200,
})
})
4.3 XML响应 #
go
r.GET("/xml", func(c *gin.Context) {
c.XML(200, gin.H{
"message": "ok",
"status": 200,
})
})
4.4 HTML响应 #
go
// 加载模板
r.LoadHTMLGlob("templates/*")
r.GET("/html", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{
"title": "Gin Demo",
})
})
4.5 文件响应 #
go
// 返回文件
r.GET("/file", func(c *gin.Context) {
c.File("/path/to/file.pdf")
})
// 文件下载
r.GET("/download", func(c *gin.Context) {
c.Header("Content-Disposition", "attachment; filename=file.pdf")
c.File("/path/to/file.pdf")
})
4.6 重定向 #
go
r.GET("/redirect", func(c *gin.Context) {
c.Redirect(302, "/new-url")
})
r.GET("/new-url", func(c *gin.Context) {
c.String(200, "Redirected!")
})
五、完整示例 #
5.1 RESTful API示例 #
go
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
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", func(c *gin.Context) {
c.JSON(http.StatusOK, users)
})
// 获取单个用户
r.GET("/users/:id", func(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": "User not found"})
})
// 创建用户
r.POST("/users", func(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)
})
// 更新用户
r.PUT("/users/:id", func(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": "User not found"})
})
// 删除用户
r.DELETE("/users/:id", func(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": "Deleted"})
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
})
r.Run(":8080")
}
5.2 测试API #
bash
# 获取所有用户
curl http://localhost:8080/users
# 获取单个用户
curl http://localhost:8080/users/1
# 创建用户
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"id":"3","name":"Charlie","age":28}'
# 更新用户
curl -X PUT http://localhost:8080/users/1 \
-H "Content-Type: application/json" \
-d '{"id":"1","name":"Alice Updated","age":26}'
# 删除用户
curl -X DELETE http://localhost:8080/users/1
六、调试技巧 #
6.1 打印路由信息 #
go
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
// 打印所有路由
routes := r.Routes()
for _, route := range routes {
fmt.Printf("%s %s\n", route.Method, route.Path)
}
r.Run()
}
6.2 请求日志 #
go
func main() {
r := gin.Default()
// 自定义日志格式
gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
log.Printf("[ROUTE] %s %s --> %s (%d handlers)\n",
httpMethod, absolutePath, handlerName, nuHandlers)
}
r.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
r.Run()
}
6.3 使用pprof #
go
import "net/http/pprof"
func main() {
r := gin.Default()
// 注册pprof路由
r.GET("/debug/pprof/*action", func(c *gin.Context) {
c.Param("action", c.Param("action")[1:])
http.HandlerFunc(pprof.Index).ServeHTTP(c.Writer, c.Request)
})
r.Run()
}
七、总结 #
7.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 创建引擎 | gin.Default() 或 gin.New() |
| 定义路由 | r.GET()、r.POST()等方法 |
| 处理函数 | func(c *gin.Context) |
| 启动服务 | r.Run() |
| Context | 请求上下文,获取参数和响应 |
7.2 下一步 #
现在你已经创建了第一个Gin应用,接下来让我们学习 项目结构,组织更复杂的项目!
最后更新:2026-03-28