GoWeb开发-1.gin框架

1.安装gin框架

go get -u github.com/gin-gonic/gin

2.运行gin

package main
import (
	"github.com/gin-gonic/gin"
	"net/http"
)
func main(){
    
    
   r := gin.Default()
   r.GET("/", func(c *gin.Context) {
    
    
		c.JSON(http.StatusOK,gin.H{
    
    
          "message":"hello world",
        })
	})
	r.Run(":9090")
}

3.运行

go run main.go

4.gin请求方式(使用REST)

  • GET用来获取资源
r.GET("/book", func(c *gin.Context) {
    
    
   	c.JSON(http.StatusOK, gin.H{
    
    
   		"message": "GET",
   	})
   })
  • POST用来新建资源
   r.POST("/book", func(c *gin.Context) {
    
    
   	c.JSON(http.StatusOK, gin.H{
    
    
   		"message": "POST",
   	})
   })
  • PUT用来更新资源
	r.PUT("/book", func(c *gin.Context) {
    
    
		c.JSON(http.StatusOK, gin.H{
    
    
			"message": "PUT",
		})
	})
  • DELETE用来删除资源。
	r.DELETE("/book", func(c *gin.Context) {
    
    
		c.JSON(http.StatusOK, gin.H{
    
    
			"message": "DELETE",
		})
	})
  • 可以请求任意
   r.Any("/book", func(c *gin.Context) {
    
    
   	c.JSON(http.StatusOK, gin.H{
    
    
   		"message": "DELETE",
   	})
   })
  • 无路由跳转
r.NoRoute(func(c *gin.Context) {
    
    
   	c.HTML(http.StatusNotFound, "views/404.html", nil)
   })
  • 请求组
v1:= r.Group("v1")
{
    
    
    v1.PUT("/book", func(c *gin.Context) {
    
    
		c.JSON(http.StatusOK, gin.H{
    
    
			"message": "PUT",
		})
	})

	v1.POST("/book", func(c *gin.Context) {
    
    
		c.JSON(http.StatusOK, gin.H{
    
    
			"message": "POST",
		})
	})
}

5.获取请求的参数

  • 获取URL上的参数
路径地址如:http://127.0.0.1:9090/user/admin/18
   r.GET("/user/:username/:age", func(c *gin.Context) {
    
    
   	username := c.Param("username")
   	age:= c.Param("age")
   	//输出json结果给调用方
   	c.JSON(http.StatusOK, gin.H{
    
    
   		"message":  "ok",
   		"username": username,
   		"age":  age,
   	})
   })
  • 获取querystring的参数

querystring指的是URL中?后面携带的参数,例如:/user/search?username=admin&age=18。 获取请求的querystring参数的方法如下

r.GET("/user/search", func(c *gin.Context) {
    
    
		username := c.DefaultQuery("username", "admin")
		//username := c.Query("username")
		age := c.Query("age")
		//输出json结果给调用方
		c.JSON(http.StatusOK, gin.H{
    
    
			"message":  "ok",
			"username": username,
			"age":  age,
		})
	})
  • 获取form的参数
	r.POST("/user/search", func(c *gin.Context) {
    
    
		// DefaultPostForm取不到值时会返回指定的默认值
		//username := c.DefaultPostForm("username", "admin")
		username := c.PostForm("username")
		age := c.PostForm("age")
		//输出json结果给调用方
		c.JSON(http.StatusOK, gin.H{
    
    
			"message":  "ok",
			"username": username,
			"age":  age,
		})
	})
  • 参数绑定

为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。 下面的示例代码演示了.ShouldBind()强大的功能,它能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象

// Binding from JSON
type Login struct {
    
    
	User     string `form:"user" json:"user" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

// 绑定JSON的示例 ({"user": "q1mi", "password": "123456"})
	router.POST("/loginJSON", func(c *gin.Context) {
    
    
		var login Login

		if err := c.ShouldBind(&login); err == nil {
    
    
			fmt.Printf("login info:%#v\n", login)
			c.JSON(http.StatusOK, gin.H{
    
    
				"user":     login.User,
				"password": login.Password,
			})
		} else {
    
    
			c.JSON(http.StatusBadRequest, gin.H{
    
    "error": err.Error()})
		}
	})

	// 绑定form表单示例 (user=q1mi&password=123456)
	router.POST("/loginForm", func(c *gin.Context) {
    
    
		var login Login
		// ShouldBind()会根据请求的Content-Type自行选择绑定器
		if err := c.ShouldBind(&login); err == nil {
    
    
			c.JSON(http.StatusOK, gin.H{
    
    
				"user":     login.User,
				"password": login.Password,
			})
		} else {
    
    
			c.JSON(http.StatusBadRequest, gin.H{
    
    "error": err.Error()})
		}
	})

	// 绑定QueryString示例 (/loginQuery?user=q1mi&password=123456)
	router.GET("/loginForm", func(c *gin.Context) {
    
    
		var login Login
		// ShouldBind()会根据请求的Content-Type自行选择绑定器
		if err := c.ShouldBind(&login); err == nil {
    
    
			c.JSON(http.StatusOK, gin.H{
    
    
				"user":     login.User,
				"password": login.Password,
			})
		} else {
    
    
			c.JSON(http.StatusBadRequest, gin.H{
    
    "error": err.Error()})
		}
	})

6.文件上传

单个文件上传

文件上传前端页面代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>上传文件示例</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="f1">
    <input type="submit" value="上传">
</form>
</body>
</html>

后端处理
	// 处理multipart forms提交文件时默认的内存限制是32 MiB
	// 可以通过下面的方式修改
	// router.MaxMultipartMemory = 8 << 20  // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
    
    
		// 单个文件
		file, err := c.FormFile("f1")
		if err != nil {
    
    
			c.JSON(http.StatusInternalServerError, gin.H{
    
    
				"message": err.Error(),
			})
			return
		}

		log.Println(file.Filename)
		dst := fmt.Sprintf("C:/tmp/%s", file.Filename)
		// 上传文件到指定的目录
		c.SaveUploadedFile(file, dst)
		c.JSON(http.StatusOK, gin.H{
    
    
			"message": fmt.Sprintf("'%s' uploaded!", file.Filename),
		})
	})

多个文件上传

	// 处理multipart forms提交文件时默认的内存限制是32 MiB
	// 可以通过下面的方式修改
	// router.MaxMultipartMemory = 8 << 20  // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
    
    
		// Multipart form
		form, _ := c.MultipartForm()
		files := form.File["file"]

		for index, file := range files {
    
    
			log.Println(file.Filename)
			dst := fmt.Sprintf("C:/tmp/%s_%d", file.Filename, index)
			// 上传文件到指定的目录
			c.SaveUploadedFile(file, dst)
		}
		c.JSON(http.StatusOK, gin.H{
    
    
			"message": fmt.Sprintf("%d files uploaded!", len(files)),
		})
	})

7.gin中间件

Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。

  • 定义中间件

Gin中的中间件必须是一个gin.HandlerFunc类型。例如我们像下面的代码一样定义一个统计请求耗时的中间件。

// StatCost 是一个统计耗时请求耗时的中间件
func StatCost() gin.HandlerFunc {
    
    
	return func(c *gin.Context) {
    
    
		start := time.Now()
		c.Set("name", "admin") // 可以通过c.Set在请求上下文中设置值,后续的处理函数能够取到该值
		// 调用该请求的剩余处理程序
		c.Next()
		// 不调用该请求的剩余处理程序
		// c.Abort()
		// 计算耗时
		cost := time.Since(start)
		log.Println(cost)
	}
}
  • 注册中间件

在gin框架中,我们可以为每个路由添加任意数量的中间件。

为全局路由注册

	// 新建一个没有任何默认中间件的路由
	r := gin.New()
	// 注册一个全局中间件
	r.Use(StatCost())

为某个路由单独注册

// 给/test2路由单独注册中间件(可注册多个)
	r.GET("/test2", StatCost(), func(c *gin.Context) {
    
    
		name := c.MustGet("name").(string) // 从上下文取值
		log.Println(name)
		c.JSON(http.StatusOK, gin.H{
    
    
			"message": "Hello world!",
		})
	})
	

猜你喜欢

转载自blog.csdn.net/qq_25064691/article/details/120612719