加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

01 . Go框架之Gin框架从入门到熟悉(路由和上传文件)

发布时间:2020-12-16 09:19:33 所属栏目:大数据 来源:网络整理
导读:Gin框架简介 Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,已经发布了1.0版本。具有快速灵活,容错方便等特点。其实对于golang而言,web框架的依赖要远比Python,Java之类的要

Gin框架简介

Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,已经发布了1.0版本。具有快速灵活,容错方便等特点。其实对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的net/http足够简单,性能也非常不错。框架更像是一些常用函数或者工具的集合。借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范。

Gin特性
/*
		快速:  路由不使用反射,基于Radix树,内存占用少
		中间件: HTTP请求,先经过一系列中间件和最终操作来处理,例如: Logger,Authorization,GZIP等,这个特性和NodeJs的Koa框架很像,中间件机制也极大的提高了框架的可扩展性.
		Cr			 
		异常处理:  服务始终可用,不会宕机,Gin可以捕获panic,并恢复,而且极为便利的机制处理HTTP请求过程中发生的错误.
    JSON:  Gin可以解析并验证请求的JSON,这个特性对于Restful API的开发尤其有用.
    路由分组:  例如需要授权和不需要授权的API分组,不同版本的API分组.
    					而且分组可嵌套,且性能不受影响.
    渲染内置:  原生支持JSON,XML和HTML的渲染.
*/
安装Gin
go get -u -v github.com/gin-gonic/gin

/*
		-v:打印出被构建的代码包的名字
		-u:已存在相关的代码包,强行更新代码包及其依赖包
*/
第一个Gin程序
package main

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

func main()  {
	// 创建一个默认的路由引擎
	r := gin.Default()

	// GET:  请求方式: /hello:  请求的路径
	// 当客户端以GET的方法请求/hello路径时,会执行后面的匿名函数
	r.GET("/hello",func(c *gin.Context) {
		
		// c.JSON:  返回JSON格式的数据
		c.JSON(200,gin.H{
			"message": "Hello World",})
	})
	
	// 启动HTTP服务,默认在0.0.0.0:8080启动服务
	r.Run()
}

/*
		1. 首先我们使用gin.Default()生成了一个实例,这个实例即WSGI应用程序.
		2. 接下来,我们使用r.Get("/",...)声明了一个路由,告诉Gin什么样的URL能触发传入的函数,这个函数返回我们想要显示在用户浏览器中的信息.
				
		3. 最后用r.Run()函数让应用运行在本地服务器上,默认监听端口是_8080_,可以传入参数,例如: r.Run(":9999")即运行在9999端口.
*/

路由

路由方法有GET,POST,PUT,PATCH,DELETEOPTIONS,还有Any,可匹配以上任意类型的请求

无参数
r.GET("/",func(c *gin.Context) {
	c.String(http.StatusOK,"wunai")
})

/*
	curl http://127.0.0.1:8080
	wunai
*/
解析路径参数

有时候我们需要动态的路由,如/user/:name,通过调用不同的url来传入不同的Name,/user/:name/*role,*代表可选

	// 匹配/user/youmen
	r.GET("/user/:name",func(c *gin.Context) {
		name := c.Param("name")
		c.String(http.StatusOK,"Hello %s",name)
	})


/*
		curl http://127.0.0.1:8080/user/youmen
		Hello youmen
*/
获取Query参数
// 匹配users?name=xxx&role=xxx,role可选
r.GET("/users",func(c *gin.Context) {
  name := c.Query("name")
  role := c.DefaultQuery("role","teacher")
  c.String(http.StatusOK,"%s is a %s",name,role)
})


/*
  curl http://127.0.0.1:8080/users?name=youmen&role=student
  youmen is a student
*/
http常见传输格式
/*
    application/json
    application/x-www-form-urlencoded 
    application/xml
    multipart/form-data 
    
    表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencoded或from-data格式的参数
*/
获取POST参数
// POST
r.POST("/form",func(c *gin.Context) {
  username := c.PostForm("username")
  password := c.DefaultPostForm("password","123") // 可设置默认值

  c.JSON(http.StatusOK,gin.H{
    "username":username,"password":password,})
})

/*
		curl http://localhost:8080/form  -X POST -d 'username=youmen&password=1234' 

		{"password":"1234","username":"youmen"}%  
*/

Example2

gin_demo1.go

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()

	// GET:  请求方式: /hello:  请求的路径
	// 当客户端以GET的方法请求/hello路径时,func(c *gin.Context) {

		// c.JSON:  返回JSON格式的数据
		c.JSON(200,})
	})

	r.POST("/form",func(c *gin.Context) {
		// 表单参数设置默认值
		type1 := c.DefaultPostForm("type","alert")

		// 接受其他的
		username := c.PostForm("username")
		password := c.PostForm("password")

		// 多选框
		hobbys := c.PostFormArray("hobby")
		c.String(http.StatusOK,fmt.Sprintf("type is %s,username is %s,password is %s,habbys is %v",type1,username,password,hobbys))
	})
	// 启动HTTP服务,默认在0.0.0.0:8080启动服务
	r.Run()
}

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <form action="http://127.0.0.1:8080/form" method="post" enctype="application/x-www-form-urlencoded">
        用户名: <input type="text" name="username">
        密码: <input type="password" name="password">

        <input type="checkbox" value="run" name="hobby"> 跑步
        <input type="checkbox" value="Weightlifting" name="hobby"> 举重
        <input type="checkbox" value="money" name="hobby"> 金钱

        <input type="submit" value="注册">
    </form>

</body>
</html>
Query和POST混合参数
	// GET和POST混合
	r.POST("/posts",func(c *gin.Context) {
		id := c.Query("id")
		page := c.DefaultQuery("page","0")
		username := c.PostForm("username")
		password := c.DefaultPostForm("username","0000")

		c.JSON(http.StatusOK,gin.H{
			"id":       id,"page":     page,"username": username,"password": password,})
	})

/*
		curl "http://localhost:8080/posts?id=9876&page=7"  -X POST -d 'username=geektutu&password=1234'

				{"id":"9876","page":"7","password":"geektutu","username":"geektutu"}%                            
*/
Map参数(字典参数)
// Map参数(字典参数)
r.POST("/post",func(c *gin.Context) {
  ids := c.QueryMap("ids")
  names := c.PostFormMap("names")

  c.JSON(http.StatusOK,gin.H{
    "ids": ids,"names": names,})
})                       

/*
		curl -g "http://localhost:8080/post?ids[Jack]=001&ids[Tom]=002" -X POST -d 'names[a]=Sam&names[b]=David'
{"ids":{"Jack":"001","Tom":"002"},"names":{"a":"Sam","b":"David"}}%     
*/
重定向(Redirect)
r.GET("/redirect",func(c *gin.Context) {
  c.Redirect(http.StatusMovedPermanently,"/index")
})

r.GET("/index",func(c *gin.Context) {
  c.Request.URL.Path = "/"
  r.HandleContext(c)
})

/*
		curl http://127.0.0.1:8080/redirect -i
		HTTP/1.1 301 Moved Permanently
		Content-Type: text/html; charset=utf-8
		Location: /index
		Date: Tue,27 Oct 2020 07:40:25 GMT
		Content-Length: 41
*/
分组路由

如果有一组路由,前缀都是/api/v1开头,是否每个路由都需要加上/api/v1这个前缀呢?答案是不需要,分组路由可以解决这个问题。利用分组路由还可以更好地实现权限控制,例如将需要登录鉴权的路由放到同一分组中去,简化权限控制。

// group routes 分组路由
defaultHandler := func(c *gin.Context) {
	c.JSON(http.StatusOK,gin.H{
		"path": c.FullPath(),})
}
// group: v1
v1 := r.Group("/v1")
{
	v1.GET("/posts",defaultHandler)
	v1.GET("/series",defaultHandler)
}
// group: v2
v2 := r.Group("/v2")
{
	v2.GET("/posts",defaultHandler)
	v2.GET("/series",defaultHandler)
}


/*
		curl http://localhost:8080/v1/posts
  	{"path":"/v1/posts"}
  	curl http://localhost:8080/v2/posts
  	{"path":"/v2/posts"}
*/

上传文件

multipart/form-data格式用于文件上传

gin文件上传与原生的net/http方法类似,不同在于gin把原生的request封装到c.Request中

上传单个文件

upload.go

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
)

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()

	// api参数
	r.POST("/upload",func(c *gin.Context) {
		// 表单取文件
		file,_ := c.FormFile("file")
		log.Println(file.Filename)

		// 传到项目根目录,名字就用本身的
		c.SaveUploadedFile(file,file.Filename)

		// 打印信息
		c.String(200,fmt.Sprintf("'%s' upload!",file.Filename))
	})
	// 启动HTTP服务,默认在0.0.0.0:8080启动服务
	r.Run()
}

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <form action="http://127.0.0.1:8080/upload" method="post" enctype="multipart/form-data">
        头像
        <input type="file" name="file">

        <input type="submit" value="提交">
    </form>
</body>
</html>
多个文件

upload.go

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()
	r.MaxMultipartMemory = 8 << 20

	r.POST("/upload",func(c *gin.Context) {
		form,err := c.MultipartForm()
		if err != nil {
			c.String(http.StatusBadRequest,fmt.Sprintf("get err %s",err.Error()))
		}

		// 获取所有图片
		files := form.File["files"]

		// 遍历所有图片
		for _,file := range files {
			// 逐个存
			if err := c.SaveUploadedFile(file,file.Filename); err != nil {
				c.String(http.StatusBadRequest,fmt.Sprintf("upload err %s",err.Error()))
				return
			}
		}

		c.String(200,fmt.Sprintf("upload ok %d files",len(files)))
	})

	// 启动HTTP服务,默认在0.0.0.0:8080启动服务
	r.Run()
}

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <form action="http://127.0.0.1:8080/upload" method="post" enctype="multipart/form-data">
        头像
        <input type="file" name="files" multiple>

        <input type="submit" value="提交">
    </form>
</body>
</html>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读