弑君者

V1

2023/01/21阅读:32主题:默认主题

Gin 入门

安装

  1. 快速入门
package main

import (
 "net/http"

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

func pong(c *gin.Context) {
 c.JSON(http.StatusOK, gin.H{
  "message""pong",
 })
}
func main() {
 // 实例化一个gin的server对象
  // Creates a gin router with default middleware:
 // logger and recovery (crash-free) middleware
 r := gin.Default()
 // 定义一个接口
 r.GET("/ping", pong)
 // 监听8083端口
 r.Run(":8083"
}

代码很简单,这样就启动了服务

  1. 使用get、post、put等方法
func main() {
 // Creates a gin router with default middleware:
 // logger and recovery (crash-free) middleware
 router := gin.Default()

 router.GET("/someGet", getting)
 router.POST("/somePost", posting)
 router.PUT("/somePut", putting)
 router.DELETE("/someDelete", deleting)
 router.PATCH("/somePatch", patching)
 router.HEAD("/someHead", head)
 router.OPTIONS("/someOptions", options)

 // By default it serves on :8080 unless a
 // PORT environment variable was defined.
 router.Run()
 // router.Run(":3000") for a hard coded port
}
  1. url和路由分组

路由分组: 每一个服务下面都有很多的接口,所以需要给每个服务建立一个分组。

package main

import (
 "net/http"

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

func main() {
 router := gin.Default()
 goodsGroup := router.Group("/goods")
 {
  goodsGroup.GET("", goodsList)
  goodsGroup.GET("/:id/:action/add", goodsDetail) //获取商品id为1的详细信息 模式
  goodsGroup.POST("", createGoods)
 }

 router.Run(":8083")
}

func createGoods(c *gin.Context) {

}

func goodsDetail(c *gin.Context) {
  // 获取参数
 id := c.Param("id")
 action := c.Param("action")
 c.JSON(http.StatusOK, gin.H{
  "id":     id,
  "action": action,
 })
}

func goodsList(context *gin.Context) {
 context.JSON(http.StatusOK, gin.H{
  "name""goodsList",
 })
}

获取url参数


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

 // This handler will match /user/john but will not match /user/ or /user
 router.GET("/user/:name"func(c *gin.Context) {
  name := c.Param("name")
  c.String(http.StatusOK, "Hello %s", name)
 })

 // However, this one will match /user/john/ and also /user/john/send
 // If no other routers match /user/john, it will redirect to /user/john/
 router.GET("/user/:name/*action"func(c *gin.Context) {
  name := c.Param("name")
  action := c.Param("action")
  message := name + " is " + action
  c.String(http.StatusOK, message)
 })

 // For each matched request Context will hold the route definition
 router.POST("/user/:name/*action"func(c *gin.Context) {
  b := c.FullPath() == "/user/:name/*action" // true
  c.String(http.StatusOK, "%t", b)
 })

 // This handler will add a new router for /user/groups.
 // Exact routes are resolved before param routes, regardless of the order they were defined.
 // Routes starting with /user/groups are never interpreted as /user/:name/... routes
 router.GET("/user/groups"func(c *gin.Context) {
  c.String(http.StatusOK, "The available groups are [...]")
 })

 router.Run(":8080")
}

从get和post 方法中获取参数

package main

import (
 "net/http"

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

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

 router.GET("/welcome", welcome)
 router.POST("/form_post", formPost)
 router.POST("/post", getPost)

 router.Run(":8083")
}

func getPost(c *gin.Context) {
 id := c.Query("id")
 page := c.DefaultQuery("page""0")
 name := c.PostForm("name")
 message := c.DefaultPostForm("message""信息")
 c.JSON(http.StatusOK, gin.H{
  "id":      id,
  "page":    page,
  "name":    name,
  "message": message,
 })
}

func formPost(c *gin.Context) {
 message := c.PostForm("message")
 nick := c.DefaultPostForm("nick""anonymous")
 c.JSON(http.StatusOK, gin.H{
  "message": message,
  "nick":    nick,
 })
}

func welcome(c *gin.Context) {
 firstName := c.DefaultQuery("firstname""bobby")
 lastName := c.DefaultQuery("lastname""imooc")
 c.JSON(http.StatusOK, gin.H{
  "first_name": firstName,
  "last_name":  lastName,
 })
}
  1. 自定义gin中间件

什么是中间件

这个和koa还有egg的中间件类似

实现一个打log的中间件

func MyLogger() gin.HandlerFunc {
 // 返回一个函数就可以了
 return func(c *gin.Context) {
  t := time.Now()
  c.Set("example""123456")
  // 让原本应该执行的逻辑继续执行
  c.Next()
  // 执行完以后,然后再执行之类的逻辑
  end := time.Since(t)
  fmt.Printf("耗时:%v\n", end)
  status := c.Writer.Status()
  fmt.Println("状态", status)
 }
}

gin 中间件原理

使用切片,如果调用了next,就会调用切片的下一个函数,这里使用了一个index索引

  1. gin 退出
package main

import (
 "context"
 "errors"
 "log"
 "net/http"
 "os"
 "os/signal"
 "syscall"
 "time"

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

func main() {
 router := gin.Default()
 router.GET("/"func(c *gin.Context) {
  time.Sleep(5 * time.Second)
  c.String(http.StatusOK, "Welcome Gin Server")
 })

 srv := &http.Server{
  Addr:    ":8080",
  Handler: router,
 }

 // Initializing the server in a goroutine so that
 // it won't block the graceful shutdown handling below
 // 在协程中使用,
 go func() {
  if err := srv.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
   log.Printf("listen: %s\n", err)
  }
 }()

 // Wait for interrupt signal to gracefully shutdown the server with
 // a timeout of 5 seconds.
 quit := make(chan os.Signal, 2)
 // kill (no param) default send syscall.SIGTERM
 // kill -2 is syscall.SIGINT
 // kill -9 is syscall.SIGKILL but can't be caught, so don't need to add it
 // 准备接受信号
 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
 <-quit
 log.Println("Shutting down server...")
 
 // The context is used to inform the server it has 5 seconds to finish
 // the request it is currently handling
 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 defer cancel()

 if err := srv.Shutdown(ctx); err != nil {
  log.Fatal("Server forced to shutdown:", err)
 }

 log.Println("Server exiting")
}

分类:

后端

标签:

后端

作者介绍

弑君者
V1