Gin框架快速入门
github地址: https://github.com/gin-gonic/gin
初体验
安装: $ go get -u github.com/gin-gonic/gin
简单实例:
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", }) }) _ = r.Run() }
启动一个HTTP服务进程,默认监听在8080端口
gin.Default实例化一个GIN对象
该对象的GET方法,参数表中分别是路径和多个handler
// GET is a shortcut for router.Handle("GET", path, handle). func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle(http.MethodGet, relativePath, handlers) }
handlerFunc的具体类型:
// HandlerFunc defines the handler used by gin middleware as return value. type HandlerFunc func(*Context)
按照这种格式定义函数:
func pong(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) } func main() { r := gin.Default() r.GET("/ping", pong) _ = r.Run(":9090") }
同时在Run中可以指定端口号,不使用默认端口号
gin.H是一个map:
// H is a shortcut for map[string]interface{} type H map[string]any
所以如下方法同理:
func pong(c *gin.Context) { var m = map[string]string{ "message": "pong", } c.JSON(http.StatusOK, m) }
初始化路由
除了上述的gin.Default方法,还可以使用gin.New来创建路由,前者会开启两个中间件,分别是Logger和Recovery:
// Default returns an Engine instance with the Logger and Recovery middleware already attached. func Default() *Engine { debugPrintWARNINGDefault() engine := New() engine.Use(Logger(), Recovery()) return engine }
Logger负责日志,Recovery负责异常处理
只使用New方法便不会开启这两个功能
配置路由:
func getting(c *gin.Context) { c.JSON(http.StatusOK,gin.H{ "message":"getting", }) } func posting(c *gin.Context) { c.JSON(http.StatusOK,gin.H{ "message":"posting", }) } func main() { router := gin.Default() router.GET("/get", getting) router.GET("/post", posting) _ = router.Run() }
路由分组
使用Group方法进行路由分组
func main() { router := gin.Default() router.GET("/goods/list",goodsList) router.POST("/goods/add",createGoods) _ = router.Run() }
使用路由分组改写,与上方同理:
func main() { router := gin.Default() goodsGroup := router.Group("/goods") goodsGroup.GET("/list", goodsList) goodsGroup.GET("/add", createGoods) _ = router.Run() }
获取参数
带参数URL:
func main() { router := gin.Default() goodsGroup := router.Group("/goods") goodsGroup.GET("/", goodsList) goodsGroup.POST("", createGoods) goodsGroup.GET("/:id", goodsDetail) _ = router.Run() } func createGoods(c *gin.Context) { c.JSON(http.StatusOK, gin.H{}) } func goodsDetail(c *gin.Context) { id := c.Param("id") c.JSON(http.StatusOK, gin.H{ "id": id, }) } func goodsList(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "list", }) }
这里id会作为参数,例如访问http://localhost:8080/1
,id便等于1
如下可扩展为多参数:
func goodsDetail(c *gin.Context) { id := c.Param("id") action := c.Param("action") c.JSON(http.StatusOK, gin.H{ "id": id, "action": action, }) }
访问http://localhost:8080/goods/1/detail
,便会携带两个参数
获取GET/POST传参:
func main() { router := gin.Default() router.GET("/welcome", welcome) router.POST("/login", login) router.POST("/post", getPost) _ = router.Run() } // 获取GET传参 func welcome(c *gin.Context) { firstName := c.DefaultQuery("firstname", "unknown") lastName := c.DefaultQuery("lastname", "unknown") c.JSON(http.StatusOK, gin.H{ "first_name": firstName, "last_name": lastName, }) } // 获取POST传参 func login(c *gin.Context) { username := c.DefaultPostForm("username", "test") password := c.DefaultPostForm("password", "test") c.JSON(http.StatusOK, gin.H{ "username": username, "password": password, }) } // 混合获取参数 func getPost(c *gin.Context) { // 获取GET参数 id := c.Query("id") page := c.DefaultQuery("page", "0") // 获取POST参数 name := c.PostForm("name") message := c.DefaultPostForm("message", "") c.JSON(http.StatusOK, gin.H{ "id": id, "page": page, "name": name, "message": message, }) }
使用如下python代码进行测试:
import requests url = "http://127.0.0.1:8080/post" data = { "name": "David", "message": "test", } params = { "id": 1, "page": 2 } resp = requests.post(url,params=params,data=data) print(resp.text)
JSON渲染
将结构体序列化为JSON字符串
func main() { router := gin.Default() router.GET("/moreJSON", moreJSON) _ = router.Run() } func moreJSON(c *gin.Context) { var message struct { Name string `json:"name"` Message string Number int } message.Name = "David" message.Message = "json test" message.Number = 20 c.JSON(http.StatusOK, message) }
表单验证
GIN提供了两种方法来进行表单验证: Must Bind / Should Bind,其中要搭配validate
接收表单请求,获取用户名和密码:
type LoginForm struct { User string `json:"user" binding:"required,min=3,max=20"` Password string `json:"password" binding:"required"` } type SignUpForm struct { Age uint8 `json:"age" binding:"gte=1,lte=130"` Name string `json:"name" binding:"required,min=3"` Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required"` RePassword string `json:"repassword" binding:"required,eqfield=Password"` } func main() { router := gin.Default() router.POST("/loginJSON", func(c *gin.Context) { var loginForm LoginForm if err := c.ShouldBind(&loginForm); err != nil { fmt.Println(err.Error()) c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "msg": "login", }) }) router.POST("/signup", func(c *gin.Context) { var signupForm SignUpForm if err := c.ShouldBind(&signupForm); err != nil { fmt.Println(err.Error()) c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } }) _ = router.Run() }
使用POST请求发送JSON数据
登录:
{ "user":"David", "password":"123" }
注册:
{ "name":"David", "age":12, "email" :"1@qq.com", "password":"123", "re_password":"123" }
自定义中间件
上文有提到,gin.Default使用了两个中间件:
// Default returns an Engine instance with the Logger and Recovery middleware already attached. func Default() *Engine { debugPrintWARNINGDefault() engine := New() engine.Use(Logger(), Recovery()) return engine }
用户可以自己定义中间件
满足如下形式即可:
// HandlerFunc defines the handler used by gin middleware as return value. type HandlerFunc func(*Context)
如下所示,用于检查token:
func TokenRequired() gin.HandlerFunc { return func(c *gin.Context) { var token string for k, v := range c.Request.Header { if k == "x-token" { token = v[0] } fmt.Println(k, v, token) } if token != "test" { c.JSON(http.StatusOK, gin.H{ "msg": "login failed", }) c.Abort() } c.Next() } } func main() { router := gin.Default() router.Use(TokenRequired()) router.GET("/ping", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) }) _ = router.Run() }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构