golang gin框架
gin框架使用 1.安装 go get gopkg.in/gin-gonic/gin.v1 2.简单的HTTP服务 package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { // 1.创建一个路由handler,默认带有 Logger 和 Recovery 两个中间件 engine := gin.Default() // 2.通过HTTP方法绑定路由规则和路由函数 engine.GET("/", func(ctx *gin.Context) { ctx.String(http.StatusOK, "hello world") }) // 3.启动路由的Run方法监听端口 engine.Run(":8080") } 3.GET请求的参数获取 3.1 获取GET请求路由的参数 (1.) 冒号:加上一个参数名组成路由参数。可以使用c.Params的方法读取其值。 路由:http://127.0.0.1:8080/user/jone ------------------------------------------------- // 冒号:加上一个参数名组成路由参数,可以获取到请求参数,请求路径如:/user/zhangsan engine.GET("/user/:name", func(ctx *gin.Context) { // 使用c.Params的方法读取其值,类型为string name := ctx.Param("name") ctx.String(http.StatusOK, "hello %s", name) // 输出:hello jone }) (2.) 除了冒号,gin还提供了星号处理参数,*号能匹配的规则就更多 星号:匹配可有可无,但需保留最后的/,否则会报404,如: http://127.0.0.1:8080/user/jone/ http://127.0.0.1:8080/user/jone/play ------------------------------------------------------------ engine.GET("/user/:name/*action", func(ctx *gin.Context) { // 使用c.Params的方法读取其值,类型为string name := ctx.Param("name") action := ctx.Param("action") ctx.String(http.StatusOK, "hello %s,action:%s", name, action) // 输出:hello jone,action:/play }) (3.)GET请求URL中通过key=value的形式,可通过c.Query()获取 // 请求示例:http://127.0.0.1:8080/welcome?first_name=tom&last_name=lucy engine.GET("/welcome", func(ctx *gin.Context) { // 使用c.DefaultQuery方法读取参数,其中当参数不存在的时候,提供一个默认值 first_name := ctx.DefaultQuery("first_name", "jone") // 使用Query方法读取正常参数,当参数不存在的时候,返回空字串 last_name := ctx.Query("last_name") ctx.String(http.StatusOK, "first_name: %s,last_name: %s", first_name, last_name) // 输出:first_name: tom,last_name: lucy }) 4.Post请求参数获取 4.1 form表单数据获取 // form表单数据获取,请求示例: // curl -X POST http://127.0.0.1:8080/form_post -H "Content-Type:application/x-www-form-urlencoded" -d "message=hello&nick=rsj217" | python -m json.tool ------------------------------------------------------------------------ engine.POST("/form_post", func(ctx *gin.Context) { message := ctx.PostForm("message") // c.PostFROM解析的是x-www-form-urlencoded或from-data的参数。 nick := ctx.DefaultPostForm("nick", "anonymous") // 调用c.JSON则返回json数据,其中gin.H封装了生成json的方式 ctx.JSON(http.StatusOK, gin.H{ "status": gin.H{ "status_code": 200, "status": "ok", }, "message": message, "nick": nick, }) }) 4.2 文件上传 // 单个文件上传,测试:curl -X POST http://127.0.0.1:8000/upload -F "upload=@/Users/ghost/Desktop/pic.jpg" -H "Content-Type: multipart/form-data" ---------------------------------------------------------------------------------- engine.POST("/upload", func(ctx *gin.Context) { //name := ctx.PostForm("name") // 使用c.Request.FormFile解析客户端文件name属性 file, header, err := ctx.Request.FormFile("upload") if err != nil { ctx.String(http.StatusBadRequest, "bad request") return } // 从header中获取文件名 fileName := header.Filename // 创建文件 out, err := os.Create(fileName) if err != nil { ctx.String(http.StatusInternalServerError, "create file failed") return } defer out.Close() // 使用os的操作,把文件数据复制到硬盘上 _, err = io.Copy(out, file) if err != nil { ctx.String(http.StatusInternalServerError, "io copy failed") return } ctx.String(http.StatusCreated, "upload success") }) 上传多个文件: router.POST("/multi/upload", func(c *gin.Context) { err := c.Request.ParseMultipartForm(200000) if err != nil { log.Fatal(err) } // 使用了c.Request.MultipartForm得到文件句柄 formdata := c.Request.MultipartForm // 获取文件数据 files := formdata.File["upload"] // 遍历文件读写 for i, _ := range files { file, err := files[i].Open() defer file.Close() if err != nil { log.Fatal(err) } out, err := os.Create(files[i].Filename) defer out.Close() if err != nil { log.Fatal(err) } _, err = io.Copy(out, file) if err != nil { log.Fatal(err) } c.String(http.StatusCreated, "upload successful") } }) 4.3 数据绑定 (1.)使用ctx.BindJSON()或者ctx.BindWith() // 数据绑定,测试:curl -X POST http://127.0.0.1:8080/login -H "Content-Type:application/x-www-form-urlencoded" -d "username=jone&password=123&age=21" | python -m json.tool engine.POST("/login", func(ctx *gin.Context) { var user User var err error contentType := ctx.Request.Header.Get("Content-Type") switch contentType { case "application/json": err = ctx.BindJSON(&user) case "application/x-www-form-urlencoded": err = ctx.BindWith(&user, binding.Form) } if err != nil { log.Fatal(err) } ctx.JSON(http.StatusOK, gin.H{ "user": user.UserName, "password": user.Password, "age": user.Age, }) }) (2.)使用c.Bind()函数 // 使用c.Bind会根据content-type自动推断绑定的参数类型 engine.POST("/login2", func(c *gin.Context) { var user User err := c.Bind(&user) if err != nil { fmt.Println(err) log.Fatal(err) } c.JSON(http.StatusOK, gin.H{ "username": user.UserName, "password": user.Password, "age": user.Age, }) 4.4 格式渲染 router.GET("/render", func(c *gin.Context) { contentType := c.DefaultQuery("content_type", "json") if contentType == "json" { // JSON格式渲染 c.JSON(http.StatusOK, gin.H{ "user": "rsj217", "passwd": "123", }) } else if contentType == "xml" { // XML格式渲染 c.XML(http.StatusOK, gin.H{ "user": "rsj217", "passwd": "123", }) } }) 4.5 重定向 router.GET("/redict/google", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, "https://google.com") }) 4.6 分组路由 v1 := router.Group("/v1") v1.GET("/login", func(c *gin.Context) { c.String(http.StatusOK, "v1 login") }) v2 := router.Group("/v2") v2.GET("/login", func(c *gin.Context) { c.String(http.StatusOK, "v2 login") }) 4.7 中间件 (1.) 中间件函数 func MiddleWare() gin.HandlerFunc { return func(c *gin.Context) { fmt.Println("before middleware") // 设置请求 c.Set("request", "clinet_request") c.Next() fmt.Println("before middleware") } } (2.)中间件定义 // 使用中间件,调用中间件函数 router.Use(MiddleWare()) { router.GET("/middleware", func(c *gin.Context) { request := c.MustGet("request").(string) // 获取请求 req, _ := c.Get("request") c.JSON(http.StatusOK, gin.H{ "middile_request": request, "request": req, }) }) } (3.)单个路由中间件 router.GET("/before", MiddleWare(), func(c *gin.Context) { request := c.MustGet("request").(string) c.JSON(http.StatusOK, gin.H{ "middile_request": request, }) }) // 使用全局CORS中间件。 // router.Use(Cors()) //rate-limit 中间件 lmt := tollbooth.NewLimiter(1, nil) lmt.SetMessage("服务繁忙,请稍后再试...") (4.) 群组中间件 authorized := router.Group("/", MyMiddelware()) // 或者这样用: authorized := router.Group("/") authorized.Use(MyMiddelware()) { authorized.POST("/login", loginEndpoint) } (5.) 使用中间件进行接口鉴权 router.GET("/auth/signin", func(c *gin.Context) { cookie := &http.Cookie{ Name: "session_id", Value: "123", Path: "/", HttpOnly: true, } http.SetCookie(c.Writer, cookie) c.String(http.StatusOK, "Login successful") }) // 使用中间件AuthMiddleWare注册之后,将会先执行AuthMiddleWare的逻辑,然后才到/home的逻辑 router.GET("/home", AuthMiddleWare(), func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "home"}) }) ----------------------------------------------------------------------- func AuthMiddleWare() gin.HandlerFunc { return func(c *gin.Context) { if cookie, err := c.Request.Cookie("session_id"); err == nil { value := cookie.Value fmt.Println(value) if value == "123" { c.Next() return } } c.JSON(http.StatusUnauthorized, gin.H{ "error": "Unauthorized", }) c.Abort() return } } 4.8 自定义router func main() { router := gin.Default() http.ListenAndServe(":8080", router) } -------------------------------------------------------- func main() { router := gin.Default() // router.Run(":80") // 这样写就可以了,下面所有代码(go1.8+)是为了优雅处理重启等动作。 srv := &http.Server{ Addr: ":80", Handler: router, ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, } go func() { // 监听请求 if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %s\n", err) } }() // 优雅Shutdown(或重启)服务 quit := make(chan os.Signal) signal.Notify(quit, os.Interrupt) // syscall.SIGKILL <-quit log.Println("Shutdown Server ...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server Shutdown:", err) } select { case <-ctx.Done(): } log.Println("Server exiting") } 4.9 静态资源加载 router := gin.Default() // 静态资源加载,本例为css,js以及资源图片 router.StaticFS("/public", http.Dir("D:/tmm/website/static")) router.StaticFile("/favicon.ico", "./resources/favicon.ico") // 通过 router.LoadHTMLGlob("website/tpl//") 导入模板根目录下所有的文件 router.LoadHTMLGlob("website/tpl/*/*") // Listen and serve on 0.0.0.0:80 router.Run(":80")
参考链接
https://www.jianshu.com/p/a31e4ee25305