Go语言(十三)Gin Web框架
时间:2022-07-25
本文章向大家介绍Go语言(十三)Gin Web框架,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Gin Web框架
简介
- 基于httprouter开发的web框架:https://github.com/gin-gonic/gin
- 提供Martini风格的API,但比Martini要快40倍
- 非常轻量级,使用简洁
Gin框架的安装与使用
- 安装: go get -u github.com/gin-gonic/gin 基本使用
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run("0.0.0.0:9090")
}
支持restful风格的API
- 把设计的API抽象成一个个资源,用URI来标识
- 针对每一个资源,使用统一的方法进行操作
- 统一的方法: GET,POST,PUT,DELETE
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Result struct {
Message string `json:"message"`
Code int `json:"code"`
}
func handleUserInfo(c *gin.Context) {
var result Result = Result{
Message: "hello",
Code: 0,
}
c.JSON(http.StatusOK,result)
}
func main() {
r := gin.Default()
r.GET("/user/info", handleUserInfo)
r.Run("0.0.0.0:9090")
}
queryString设计
- 查询类:http://127.0.0.1:9090/user/info?username=dadasd&&passwd=1234
- 路由类:http://127.0.0.1:9090/user/info/2020/12
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Result struct {
Message string `json:"message"`
Code int `json:"code"`
}
type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
}
func handleUserParams(c *gin.Context) {
//查询类接口
username := c.Query("username")
passwd := c.DefaultQuery("passwd","adcdefg")
var result UserInfo = UserInfo{
Result{
Message: "success",
Code: 200,
},
username,
passwd,
}
c.JSON(http.StatusOK,result)
}
func handleUserInfo(c *gin.Context) {
//路由类接口
username := c.Param("username")
passwd := c.Param("passwd")
var result UserInfo = UserInfo{
Result{
Message: "success",
Code: 200,
},
username,
passwd,
}
c.JSON(http.StatusOK,result)
}
func main() {
r := gin.Default()
r.GET("/user/info", handleUserParams)
r.GET("/user/info/:username/:passwd", handleUserInfo)
r.Run("0.0.0.0:9090")
}
Gin框架参数传递
获取表单参数
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Result struct {
Message string `json:"message"`
Code int `json:"code"`
}
type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
}
func handleUserInfo(c *gin.Context) {
username := c.PostForm("username")
passwd := c.PostForm("passwd")
var result UserInfo = UserInfo{
Result: Result{
Message: "success",
Code: 200,
},
UserName: username,
Passwd: passwd,
}
c.JSON(http.StatusOK,result)
}
func main() {
r := gin.Default()
r.POST("/user/info",handleUserInfo)
r.Run(":9090")
}
单文件上传
func handleUpload(c *gin.Context) {
file,err := c.FormFile("testfile")
if err != nil {
fmt.Printf("upload file faild,err:%vn",err)
return
}
//文件上传路径
filename := fmt.Sprintf("/Users/wanghui/go/src/oldBoy/day8/tmp/%s",file.Filename)
//文件保存
err = c.SaveUploadedFile(file,filename)
if err != nil {
fmt.Printf("save file faild,err:%vn",err)
return
}
//状态返回
c.JSON(http.StatusOK,"file upload success")
}
func main() {
r := gin.Default()
r.POST("/file/upload",handleUpload)
r.Run(":9090")
}
多文件上传
func multiHandleUpload(c *gin.Context) {
//多文件上传
form,err := c.MultipartForm()
if err != nil {
fmt.Printf("upload file faild,err:%vn",err)
return
}
files := form.File["testfile"]
for _,file := range files {
filename := fmt.Sprintf("/Users/wanghui/go/src/oldBoy/day8/tmp/%s",file.Filename)
err = c.SaveUploadedFile(file,filename)
if err != nil {
fmt.Printf("save file faild,err:%vn",err)
return
}
}
//状态返回
c.JSON(http.StatusOK,"file upload success")
}
func main() {
r := gin.Default()
r.POST("/file/upload",handleUpload)
r.POST("/files",multiHandleUpload)
r.Run(":9090")
}
通过postman上传文件
路由分组
func main() {
r := gin.Default()
v1Group := r.Group("/v1")
v1Group.POST("/user/info",handleUserInfo)
v1Group.POST("/user/info2",handleUserInfo)
r.Run(":9090")
}
gin的参数绑定
- 为什么要使用参数绑定
- 通过反射的机制,自动提取querystring、form表单,json,xml等参数到struct中
- 通过http协议中的content type,识别是json,xml或者表单
type UserInfo struct {
UserName string `form:"username" json:"username" binding:"required"`
Passwd string `form:"passwd" json:"passwd" binding:"required"`
Age int `form:"age" json:"age" binding:"required"`
Sex string `form:"sex" json:"sex" binding:"required"`
}
func PostUserInfo(c *gin.Context) {
var UserInfo UserInfo
//表单绑定,使用指针
err := c.ShouldBind(&UserInfo)
if err != nil {
return
}
c.JSON(http.StatusOK,UserInfo)
}
func PostUserInfoJson(c *gin.Context) {
var UserInfo UserInfo
//表单绑定,使用指针
err := c.ShouldBindJSON(&UserInfo)
if err != nil {
return
}
c.JSON(http.StatusOK,UserInfo)
}
func GetUserInfoJson(c *gin.Context) {
var UserInfo UserInfo
//表单绑定,使用指针
err := c.ShouldBindJSON(&UserInfo)
if err != nil {
return
}
c.JSON(http.StatusOK,UserInfo)
}
func main() {
r := gin.Default()
v1Group := r.Group("/v1")
v1Group.POST("/user/infos",PostUserInfo)
v1Group.POST("/user/infojson",PostUserInfoJson)
v1Group.GET("/user/info",GetUserInfoJson)
r.Run(":9090")
}
渲染
- gin.Context.JSON方法进行渲染
type UserInfo struct {
UserName string `form:"username" json:"username" binding:"required"`
Passwd string `form:"passwd" json:"passwd" binding:"required"`
}
func GetUserInfoJson(c *gin.Context) {
var userInfo = &UserInfo{
UserName: "zhansan",
Passwd: "aaaa",
}
c.XML(200,userInfo)
}
func main() {
r := gin.Default()
v1Group := r.Group("/v1")
v1Group.GET("/user/info",GetUserInfoJson)
r.Run(":9090")
}
HTML模板渲染
- templates/post.html
{{ define "index.tmpl" }}
<html><h1>
{{ . }}
</h1>
<p>Using posts/index.tmpl</p>
</html>
{{ end }}
- server.go
func HandleHtmml(c *gin.Context) {
c.HTML(200,"index.tmpl","mmmmmmmm")
}
func main() {
r := gin.Default()
r.LoadHTMLGlob("./templates/*")
r.GET("/user/info",HandleHtmml)
r.Run(":9090")
}
gin中间件
- gin框架在请求处理过程中,加入用户自己的钩子函数,这个钩子函数就叫做中间件
- 因此,可以使用中间件处理一些公共业务逻辑,比如耗时统计,日志打印,登录校验等
func StatCost(c *gin.Context) {
//中间件
start := time.Now()
fmt.Printf("start n")
c.Next()
lattacy := time.Since(start)
fmt.Printf("cost Time is %dmsn", lattacy/1000/1000)
}
func funcHello(c *gin.Context) {
fmt.Printf("request startn")
time.Sleep(time.Second * 3)
c.JSON(http.StatusOK, "hello world")
}
func main() {
r := gin.Default()
r.Use(StatCost)
r.GET("/hello", funcHello)
r.Run(":9090")
}
gin框架路由原理
- 路由部分使用的是:https://github.com/julienschmidt/httprouter
- 对于路由的规则,httprouter会构造一颗前缀树
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PyQt5 技术篇-在clipboard.dataChanged.connect()里如何写入剪切板示例演示,pyqt5监听剪切板变动并写入剪切板内容
- 去除WordPress链接中出现的index.php
- MySQL 语法问题:You can‘t specify target table ‘xxx‘ for update in FROM clause. 原因及解决方法
- 配置 prometheus-operator 报警规则
- SQL语句查询出的数据进行字符串拼接,oracle批量删除数据库用户实例演示
- prometheus-operator 监控 k8s 外部集群
- Python+selenium 自动化-操作已启用的chrome浏览器实例演示,chrome启用调试端口方法
- JavaScript 技术篇-js检测原生对象类型实例演示,js的3种对象类型
- Python 技术篇-利用pyqt5库读取剪切板已复制数据的格式类型实例演示,python判断复制文件的文件类型
- 第36期:二叉树的遍历(小白必看)
- Python 技术篇-index()字符串倒叙匹配获取索引,字符串切片反向输出,逆向输出字符串
- JavaScript 技术篇-navigator.permissions读取chrome剪切板权限获取不生效原因:只有在https协议下使用有效。手动设置chrome页面剪切板读取权限方法
- 生产prometheus-operator 监控二进制kubernetes
- Excel 技术篇-跨页签统计某一区域下符合条件值的数量方法,COUNTIF函数、数量统计公式的用法实例演示
- Oracle 数据库用户锁定与解锁,用户锁定最大密码失败次数设置方法,ORA-28000: the account is locked问题解决方法