gin框架的簡單使用

gin框架是基於golang語言的web框架。如果用gin實現服務,有下述的場景需求,那麼可以繼續閱覽:

  • 服務針對不同的路由,有不同的驗證規則。比如服務對應PC管理端和移動端,分別有不同的驗證規則,涉及路由組、中間件攔截驗證;
  • 請求記錄、操作日誌按照時間每天記錄到文件中。涉及中間件日誌操作;
  • 跨域問題,涉及中間件跨域;
  • API的使用,涉及常用的POST,PUT,GET,DELETE。

代碼示意:

package main
import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"time"
	"github.com/gin-gonic/gin"
)
type User struct {
	Name string `json:"name"`
	Age int `json:"age"`
}
func main(){
	gin.SetMode(gin.DebugMode)
	router := gin.New()
	router.Use(LoggerByTime())//中間件:日誌
	router.Use(gin.Recovery())
	router.Use(Cors())//中間件:跨域

	api:=router.Group("/pc").Use(AuthRequiredPc)//pc開頭的路由中間件:驗證
	{
		api.POST("/add", func(c *gin.Context) {//參數方式:body
			var (
				user User
				rtn Rtn
				)
			err := c.ShouldBindJSON(&user)
			if err != nil {
				fmt.Fprintln(GetLogFileName(), "Add:"+err.Error())
				rtn.R = 0
				rtn.Err = err.Error()
				c.JSON(http.StatusInternalServerError,rtn)
				panic(err)
				return
			}
			fmt.Fprintln(GetLogFileName(), "添加了一個用戶,名="+user.Name+",年齡="+strconv.Itoa(user.Age))
			rtn.R = 1
			c.JSON(http.StatusOK,rtn)
		})
		api.PUT("/edit", func(c *gin.Context) {//參數方式:body
			var (
				user User
				rtn Rtn
			)
			err := c.ShouldBindJSON(&user)
			if err != nil {
				fmt.Fprintln(GetLogFileName(), "Edit:"+err.Error())
				rtn.R = 0
				rtn.Err = err.Error()
				c.JSON(http.StatusInternalServerError,rtn)
				panic(err)
				return
			}
			fmt.Fprintln(GetLogFileName(), "編輯了用戶,名="+user.Name+",年齡="+strconv.Itoa(user.Age))
			rtn.R = 1
			c.JSON(http.StatusOK,rtn)
		})
		api.DELETE("/del", func(c *gin.Context) {//參數方式:post form
			var rtn Rtn
			name := c.PostForm("name")
			fmt.Fprintln(GetLogFileName(), "刪除用戶名="+name)
			rtn.R = 1
			c.JSON(http.StatusOK,rtn)
		})
	}
	apiOut:=router.Group("/mobile").Use(AuthRequiredMobile)//mobile開頭的路由中間件:驗證
	{
		apiOut.GET("/detail", func(c *gin.Context) {//參數方式:query
			var rtn Rtn
			name := c.Query("name")
			fmt.Fprintln(GetLogFileName(), "詳情:"+"該用戶名="+name)
			rtn.R = 1
			c.JSON(http.StatusOK,rtn)
		})
	}

	router.Run(":8888")
}

//中間件:日誌。參考gin自帶的日誌中間件實現日誌按照天存儲,詳見gin/logger.go部分
func GetLogFileName()*os.File{
	filename:=fmt.Sprintf("./%s",time.Now().Format("20060102"))
	fileObj,_ := os.OpenFile(filename,os.O_RDWR|os.O_CREATE|os.O_APPEND,0777)
	return fileObj
}
type logger struct{
	Time string// Time shows the time after the server returns a response.
	StatusCode int// StatusCode is HTTP response code.
	Latency string// Latency is how much time the server cost to process a certain request.
	ClientIP string// ClientIP equals Context's ClientIP method.
	Method string// Method is the HTTP method given to the request.
	Path string// Path is a path the client requests.
}
func LoggerByTime() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Start timer
		start := time.Now()
		path := c.Request.URL.Path
		raw := c.Request.URL.RawQuery
		// Process request
		c.Next()
		param := logger{}
		// Stop timer
		param.Time = time.Now().Format("2006-01-02 15:04:05")
		param.Latency = fmt.Sprintf("%dms",time.Now().Sub(start).Nanoseconds()/1e6)
		param.ClientIP = c.ClientIP()
		param.Method = c.Request.Method
		param.StatusCode = c.Writer.Status()
		if raw != "" {
			path = path + "?" + raw
		}
		param.Path = path
		paramStr, _ := json.Marshal(param)
		fmt.Fprintln(GetLogFileName(), string(paramStr))
	}
}

//中間件:跨域。可根據自己需求進行調整
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
		origin := c.Request.Header.Get("Origin")
		if origin != "" {
			c.Header("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
			c.Header("Access-Control-Allow-Headers", "Origin,Authorization,Content-Length,Content-Type,Date,DataField")
			c.Header("Access-Control-Max-Age", "3600")
			c.Header("Access-Control-Allow-Credentials", "true")
		}
		if method == "OPTIONS" {
			c.JSON(http.StatusOK, "Options Request!")
		}
		c.Next()
	}
}

//中間件:攔截校驗
//攔截校驗
type Rtn struct {
	R int    `json:"r"`
	Data interface{} `json:"data"`
	Err  string `json:"err"`
}
func AuthRequiredPc(c *gin.Context){
	var rtn Rtn
	var err error
	authorization := c.Request.Header.Get("Authorization")
	if authorization != "pc"{
		rtn.Data=0
		err = errors.New("authen error!")
		fmt.Fprintln(GetLogFileName(), "AuthRequired:"+err.Error())
		rtn.Err = err.Error()
		c.JSON(http.StatusInternalServerError,rtn)
		panic(err)
		return
	}
}
func AuthRequiredMobile(c *gin.Context){
	var rtn Rtn
	var err error
	authorization := c.Request.Header.Get("Authorization")
	if authorization != "mobile"{
		rtn.Data=0
		err = errors.New("authen error!")
		fmt.Fprintln(GetLogFileName(), "AuthRequired:"+err.Error())
		rtn.Err = err.Error()
		c.JSON(http.StatusInternalServerError,rtn)
		panic(err)
		return
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章