学习go gin框架

1 篇文章 0 订阅

1、路由 - Restful风格

package main

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

func main()  {
	//返回默认的路由引擎
	r := gin.Default()

	//Restful风格请求,使用postman工具请求测试
	//获取
	r.GET("/hello", func(c *gin.Context) {
		c.JSON(200,gin.H{
			"message":"Hello Golang",
			"method":"GET",
		})
	})
	//创建
	r.POST("/hello", func(c *gin.Context) {
		c.JSON(http.StatusOK,gin.H{
			"message":"Hello Golang",
			"method":"POST",
		})
	})
	//更新
	r.PUT("/hello", func(c *gin.Context) {
		c.JSON(http.StatusOK,gin.H{
			"message":"Hello Golang",
			"method":"PUT",
		})
	})
	//删除
	r.DELETE("/hello", func(c *gin.Context) {
		c.JSON(http.StatusOK,gin.H{
			"message":"Hello Golang",
			"method":"DELETE",
		})
	})

	//启动服务,默认8080端口
	r.Run()
	//自定义端口
	//r.Run(":9090")
}

2、路由参数

1 - 路径参数

package main

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

func main(){
	r := gin.Default()
	//第一种访问:/user/:?/:?
	url := "/user/:name/:age/*action"

	r.GET(url, func(c *gin.Context) {
		name := c.Param("name")
		age := c.Param("age")
		//截取
		action := strings.Trim(c.Param("action"),"/")
		fmt.Println("action=",action)

		c.String(http.StatusOK,"姓名:" + name + ",年龄:" + age)
	})

	r.Run()
}

在这里插入图片描述
2 - query参数

package main

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

func main(){
	r := gin.Default()
	//第二种访问:/user?xx=xxx
	url := "/user"

	r.GET(url, func(c *gin.Context) {
		name := c.Query("name")
		age := c.Query("age")

		c.String(http.StatusOK,"姓名:" + name + ",年龄:" + age)
	})

	r.Run()
}

在这里插入图片描述
3 - 表单参数

package main

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

func main(){
	r := gin.Default()
	//表单访问:/user
	url := "/form"

	r.POST(url, func(c *gin.Context) {
		name := c.PostForm("name")
		age := c.PostForm("age")

		c.String(http.StatusOK,"姓名:" + name + ",年龄:" + age)
	})

	r.Run()
}

#form.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/form" method="post">
  用户名:<input type="text" name="name" placeholder="请输入你的用户名" value="JackyChen"></br>
  年龄:<input type="text" name="age" placeholder="请输入你的年龄" value="18"></br>
    <button type="submit">提交</button>
</form>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
4 - 默认参数

package main

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

func main(){
	r := gin.Default()
	//默认参数访问:http://localhost:8080/user
	//带参数访问:http://localhost:8080/user?name=JackyChen&age=18
	url := "/user"
	r.GET(url, func(c *gin.Context) {
		name := c.DefaultQuery("name","JackyChen")
		age := c.DefaultQuery("age","25")
		c.String(http.StatusOK,"姓名:" + name + ",年龄:" + age)
	})
	
	//当表单参数不存在name,age时,使用默认参数
	url = "/form"
	r.POST(url, func(c *gin.Context) {
		name := c.DefaultPostForm("name","JackyChen")
		age := c.DefaultPostForm("age","25")
		c.String(http.StatusOK,"姓名:" + name + ",年龄:" + age)
	})

	r.Run()
}

3、上传文件

1 - 上传单个文件

package main

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

func main()  {
	r := gin.Default()
	
	r.POST("/upload", func(c *gin.Context) {
		//获取上传文件
		//file, err := c.FormFile("file")
		_, file, err := c.Request.FormFile("file")
		if err != nil{
			c.String(http.StatusOK,"上传图片错误")
		}

		//获取文件大小
		fmt.Println(file.Size)
		//获取文件类型
		fmt.Println(file.Header.Get("Content-Type"))

		//保存文件到当前目录下./file.Filename(文件名)
		_ = c.SaveUploadedFile(file,file.Filename)
		c.String(http.StatusOK,file.Filename)
	})

	r.Run()
}

# single.html 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
    上传文件:<input type="file" name="file" >
    <input type="submit" value="提交">
</form>
</body>
</html>

2 - 上传多个文件

package main

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

func main()  {
	r := gin.Default()
	//限制表单上传大小 8MB,默认为32MB
	r.MaxMultipartMemory = 8 << 20
	r.POST("/uploads", func(c *gin.Context) {
		//获取表单大小,限制200000
		//err := c.Request.ParseMultipartForm(200000)
		//form := c.Request.MultipartForm
		
		//获取表单
		form, err := c.MultipartForm()
		if err != nil {
			c.String(http.StatusOK,"上传图片错误")
		}
		//获取所有图片数组
		files := form.File["files"]
		//循环存储
		for _, file := range files {
			if err := c.SaveUploadedFile(file,file.Filename); err != nil {
				c.String(http.StatusBadRequest,"upload err %s",err.Error())
				return
			}
		}
		c.String(http.StatusOK,"上传成功")
	})

	r.Run()
}

# multi.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/uploads" method="post" enctype="multipart/form-data">
    上传文件:<input type="file" name="files" multiple>
    <input type="submit" value="提交">
</form>
</body>
</html>

路由分组

package main

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

func main()  {
	r := gin.Default()
	//默认使用了2个中间件Logger(), Recovery()
	//创建路由组
	group := r.Group("/group")
	// {} 是书写规范
	{
		group.GET("/login",login)
		group.GET("/register",register)
	}

	r.Run()
}

func login(c *gin.Context)  {
	c.String(http.StatusOK,"login")
}

func register(c *gin.Context)  {
	c.String(http.StatusOK,"register")
}

在这里插入图片描述

路由注册与拆分

1 - 根据功能模块拆分

# main.go

package main

import (
	"gin/5-RouteSplitRegister/routers"
	"github.com/gin-gonic/gin"
)

func main()  {
	r := gin.Default()
	routers.LoadBlog(r)
	routers.LoadShop(r)
	r.Run()
}

# blog.go

package routers

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

func commentHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello comment",
	})
}

func forwardHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello forward",
	})
}

func LoadBlog(e *gin.Engine) {
	e.GET("/comment",commentHandler)
	e.GET("/forward",forwardHandler)
}

# shop.go

package routers

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

func buyHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello buy",
	})
}

func collectHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello collect",
	})
}

func LoadShop(e *gin.Engine) {
	e.GET("/buy",buyHandler)
	e.GET("/collect",collectHandler)
}

在这里插入图片描述
2 - 根据app应用拆分

# main.go

package main

import (
	"gin/5-RouteSplitRegister/app/blog"
	"gin/5-RouteSplitRegister/app/shop"
	"gin/5-RouteSplitRegister/routers"
)

func main()  {
	//根据app应用拆分
	routers.Include(blog.Routers,shop.Routers)
	r := routers.Init()

	//根据功能模块拆分
	routers.LoadBlog(r)
	routers.LoadShop(r)
	r.Run()
}

# routers.go
package routers

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

//定义路由结构体匿名方法
type Option func(*gin.Engine)
//定义路由方法数组
var options = []Option{}

//注册app路由配置
func Include(opts ...Option)  {
	options = append(options,opts...)
}

//初始化路由
func Init() *gin.Engine {
	r := gin.New()
	for _, opt := range options {
		opt(r)
	}
	return  r
}

# blog/router.go
package blog

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

func Routers(e *gin.Engine) {
	e.GET("/star",starHandler)
	e.GET("/share",shareHandler)
}
# blog/hanlder.go
package blog

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

func starHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello star",
	})
}

func shareHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello share",
	})
}

# shop/router.go
package shop

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

func Routers(e *gin.Engine) {
	e.GET("/login",loginHandler)
	e.GET("/register",registerHandler)
}
# shop/hanlder.go
package shop

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

func loginHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello login",
	})
}

func registerHandler(c *gin.Context)  {
	c.JSON(http.StatusOK,gin.H{
		"message":"Hello register",
	})
}

在这里插入图片描述

6、参数绑定

package main

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

//定义参数绑定结构体
type UserInfo struct {
	// binding:"required"修饰的字段,若接收为空值,则报错,是必须字段
	//json:"user" uri:"user" xml:"user" 指定接收的数据类型
	Username string `form:"username" binding:"required"`
	Password string `form:"password" binding:"required"`
}

func main()  {
	r := gin.Default()
	r.GET("/binding", func(c *gin.Context) {
		//声明接收的变量
		var json UserInfo
		//根据结构体tag反射解析自动绑定
		//ShouldBind能根据请求的数据类型采用对应类型绑定数据
		err := c.ShouldBind(&json)

		if err != nil {
			c.JSON(http.StatusBadRequest,gin.H{
				"error":err.Error(),
			})
		}else{
			fmt.Println("username=",json.Username,", password=",json.Password)
			c.JSON(http.StatusOK,gin.H{
				"message":"ok",
			})
		}
	})
	r.Run()
}

7、响应数据

package main

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

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

	// json响应
	r.GET("/json", func(c *gin.Context) {
		c.JSON(http.StatusOK,gin.H{
			"message":"response json",
		})
	})

	// 结构体响应
	r.GET("/struct", func(c *gin.Context) {
		var msg struct {
			Name string
			Message string
		}
		msg.Name = "JackyChen"
		msg.Message = "response struct"
		c.JSON(http.StatusOK,msg)
	})

	// XML响应
	r.GET("/xml", func(c *gin.Context) {
		c.XML(http.StatusOK,gin.H{
			"message":"response XML",
		})
	})

	// YAML响应
	r.GET("/yaml", func(c *gin.Context) {
		c.YAML(http.StatusOK,gin.H{
			"message":"response YAML",
		})
	})

	r.Run()
}

8、模板渲染

1 - 模板加载

package main

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

func main()  {
	r := gin.Default()
	//获取当前文件路径
	dir , _ := os.Getwd()
	fmt.Println(dir)
	//加载解析模板文件
	//r.LoadHTMLFiles("web.html")
	//r.LoadHTMLFiles("./html/web.html")
	//加载目录下所有文件
	//r.LoadHTMLGlob("html/*")
	//加载目录下的目录下所有文件,**代表目录
	r.LoadHTMLGlob("html/**/*")

	r.GET("/web", func(c *gin.Context) {
		//渲染模板页面 {{ . }} 点即代表整个数据,所以 .title 拿到具体数据
		c.HTML(http.StatusOK,"user.html",gin.H{
			"title":"template render",
		})
	})

	r.Run()
}

在这里插入图片描述
2 - 自定义模板名称

# 当一个目录下,存在名字相同的html文件时,此时需要自定义模板文件名称

package main

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

func main()  {
	r := gin.Default()
	//加载目录下所有文件
	r.LoadHTMLGlob("html/**/*")

	r.GET("/web", func(c *gin.Context) {
		//渲染模板页面 {{ . }} 点即代表整个数据,所以 .title 拿到具体数据
		c.HTML(http.StatusOK,"user/index.html",gin.H{
			"title":"template render",
		})
	})

	r.Run()
}

# html/common/index.html
{{ define "common/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>common/index.html</h1>
</body>
</html>
{{end}}

# html/user/index.html
{{ define "user/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>user/index.html</h1>
</body>
</html>
{{end}}

在这里插入图片描述
3 - 静态文件

package main

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

func main()  {
	r := gin.Default()
	//加载静态目录,以statics开头的,在./static目录下查找
	r.Static("statics","./static")
	//加载模板文件
	r.LoadHTMLFiles("web.html")

	r.GET("/web", func(c *gin.Context) {
		//渲染模板页面 {{ . }} 点即代表整个数据,所以 .title 拿到具体数据
		c.HTML(http.StatusOK,"web.html",gin.H{
			"title":"template render",
		})
	})

	r.Run()
}

在这里插入图片描述
4 - 公共模板

package main

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

func main()  {
	r := gin.Default()
	//加载静态目录,以statics开头的,在./static目录下查找
	r.Static("statics","./static")
	//加载模板文件
	r.LoadHTMLGlob("public/*")

	r.GET("/web", func(c *gin.Context) {
		//渲染模板页面 {{ . }} 点即代表整个数据,所以 .title 拿到具体数据
		c.HTML(http.StatusOK,"web.html",gin.H{
			"title":"template render",
		})
	})

	r.Run()
}

# web.html
{{ define "web.html" }}
{{template "header.html" .}}
<h1>{{.title}}</h1>
{{template "footer.html" .}}
{{ end }}

# header.html
{{define "header.html"}}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="statics/common.css">
  <title>Title</title>
</head>
<body>
{{end}}

# footer.html
{{define "footer.html"}}
</body>
</html>
{{end}}

在这里插入图片描述

9、重定向

package main

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

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

	r.GET("/redirect", func(c *gin.Context) {
		//301永久重定向
		c.Redirect(http.StatusMovedPermanently,"http://www.baidu.com")
	})

	r.Run()
}

10、同步和异步

package main

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

func main()  {
	r := gin.Default()
	//异步,请求成功,等待3秒打印
	r.GET("/async", func(c *gin.Context) {
		//异步原因,需要副本
		cp := c.Copy()
		go func() {
			time.Sleep(time.Second * 3)
			fmt.Println("异步执行:"+cp.Request.URL.Path)
		}()
	})
	//同步,请求和打印几乎同时
	r.GET("/sync", func(c *gin.Context) {
		time.Sleep(time.Second * 3)
		fmt.Println("同步执行:"+c.Request.URL.Path)
	})

	r.Run()
}

11、中间件

1 - 全局中间件

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)
//定义全局中间件
func GlobalMiddleWare1() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("is a GlobalMiddleWare1")
	}
}
func GlobalMiddleWare2() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("is a GlobalMiddleWare2")
	}
}

func main()  {
	r := gin.Default()
	//注册全局中间件
	r.Use(GlobalMiddleWare1(),GlobalMiddleWare2())

	r.GET("/middleware", func(c *gin.Context) {
		c.JSON(http.StatusOK,gin.H{
			"message":"middleware",
		})
	} )

	r.Run()
}

2 - 局部中间件

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)
//定义局部中间件
func MiddleWare(c *gin.Context) {
	fmt.Println("is a MiddleWare")
}

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

	r.GET("/middleware",MiddleWare, func(c *gin.Context) {
		c.JSON(http.StatusOK,gin.H{
			"message":"middleware",
		})
	} )

	r.Run()
}

3 - next()和abort()

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)
//定义局部中间件,统计请求处理函数的耗时
func middleWare(c *gin.Context) {
	fmt.Println("middleWare start...")
	//获取现在时间
	start := time.Now()

	name := c.Query("name")
	if name != "" {
		c.Next()	//调用后续的处理函数
	}else {
		c.Abort()	//阻止调用后续的处理函数
	}
	//计算耗时
	cost := time.Since(start)
	fmt.Printf("cost = %v\n",cost)
	fmt.Println("middleWare end...")
}

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

	r.GET("/middleware",middleWare, func(c *gin.Context) {
		count := 0;
		for i := 1; i < 10000000; i++ {
			count += i
		}
		c.JSON(http.StatusOK,gin.H{
			"count":count,
		})
	} )

	r.Run()
}

5 - 中间件数据通信

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)
//定义全局中间件
func m1() gin.HandlerFunc {
	return func(c *gin.Context) {
		//设置任意类型数据
		c.Set("name","JackyCHen")
	}
}

func main()  {
	r := gin.Default()
	//注册全局中间件
	r.Use(m1())

	r.GET("/middleware", func(c *gin.Context) {
		//获取值
		name,_ := c.Get("name")
		c.JSON(http.StatusOK,gin.H{
			"name":name,
		})
	} )

	r.Run()
}

6 - 路由组中间件

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)
//定义全局中间件
func M1() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Println("is a MiddleWare")
	}
}

func main()  {
	r := gin.Default()
	//设置路由组
	group := r.Group("/m")
	//路由组注册全局中间件
	group.Use(M1())
	{
		group.GET("/middleware1", func(c *gin.Context) {
			//获取值
			c.JSON(http.StatusOK,gin.H{
				"message":"middleware1",
			})
		} )

		group.GET("/middleware2", func(c *gin.Context) {
			c.JSON(http.StatusOK,gin.H{
				"message":"middleware2",
			})
		} )
	}

	r.Run()
}

12、会话控制

1 - cookie

package main

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

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

	r.GET("/cookie", func(c *gin.Context) {
		//获取客户端传递的cookie
		cookie, err := c.Cookie("name")
		if err != nil {
			cookie = "JackyChen"
		}else{
			cookie = "cxhblog"
		}
		// 给客户端设置cookie
		//  maxAge int, 存活时间,单位为秒
		// path,cookie所在目录
		// domain string,域名
		//   secure 是否智能通过https访问
		// httpOnly bool  是否允许别人通过js获取自己的cookie
		c.SetCookie("name",cookie,60,"/","localhost",false,true)
		fmt.Printf("cookie = %v\n",cookie)
	})

	r.Run()
}

2 - session

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/sessions"
	"net/http"
)
//初始化cookie存储对象,"something-very-secret" 为随机密钥
var store = sessions.NewCookieStore([]byte("something-very-secret"))

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

	r.GET("/getSession", func(c *gin.Context) {
		//获取session对象,"session-name" session名称,可任意命名
		session, err := store.Get(c.Request,"session-name")
		if err != nil {
			c.JSON(http.StatusOK,gin.H{
				"error":err.Error(),
			})
		}
		//获取session值
		
		getSessionName := session.Values["name"]
		fmt.Printf("getSessionName = %v\n",getSessionName)
	})

	r.GET("/setSession", func(c *gin.Context) {
		//获取session对象,"session-name" session名称,可任意命名
		session, err := store.Get(c.Request,"session-name")
		if err != nil {
			c.JSON(http.StatusOK,gin.H{
				"error":err.Error(),
			})
		}
		//设置session值
		setSessionName := "cxhblog"
		session.Values["name"] = setSessionName
		//保存更改
		session.Save(c.Request,c.Writer)
		fmt.Printf("setSessionName = %v\n",setSessionName)
	})

	r.Run()
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值