Go 之 Gin 框架

Gin 是一个 Go (Golang) 编写的轻量级 web 框架,运行速度非常快,擅长 Api 接口的高并发,如果项目的规模不大,业务相对简单,这个时候我们也推荐您使用 Gin,特别适合微服务框架。

简单路由配置

package mainimport ("github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎r := gin.Default()// 配置路由r.GET("/", func(c *gin.Context) {aid := c.Query("aid")c.JSON(200, gin.H{"username": "name1","aid": aid,"data": []string{"hello", "world"},})})// 启动 HTTP 服务,默认在 0.0.0.0:8080 启动服务r.Run()
}

运行起来以后,在浏览器输入http://127.0.0.1:8080/?aid=xyz,即可获取到 url 请求的结果

{"aid":"xyz","data":["hello","world"],"username":"name1"}

动态路由

package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/user/:id", func(c *gin.Context) {id := c.Param("id")c.JSON(200, gin.H{"username": "name1","id": id,"data": []string{"hello", "world"},})})r.Run()
}

请求 url:http://127.0.0.1:8080/user/looking

请求 result:

{"data":["hello","world"],"id":"looking","username":"name1"}

结果响应

c.String()

package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/news", func(c *gin.Context) {c.String(200, "Hello world")})r.Run()
}

c.JSON()

大部分时候,我们直接返回 json 的数据格式要更多一些。数据返回我们可以使用 gin.H 的 map 形式,也可以直接用 struct 的形式,不过使用结构体的话,记得要给字段标注好 json 对应的 tag。

package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/structJson", func(c *gin.Context) {// 结构体方式var msg struct {Username string `json:"username"`Msg string `json:"msg"`Age string `json:"age"`}msg.Username = "name1"msg.Msg = "msg1"msg.Age = "18"c.JSON(200, msg)})r.Run()
}

c.JSONP()

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.GET("/JSONP", func(c *gin.Context) {data := map[string]interface{}{"foo": "bar",}c.JSONP(http.StatusOK, data)})r.Run()
}

请求 url:http://127.0.0.1:8080/JSONP?callback=x

请求 result:

x({"foo":"bar"});

c.HTML()

index.html

<!DOCTYPE  html>
<html  lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>
<h1>这是一个 html 模板</h1><h3>{{.title}}</h3>
</body>
</html>

渲染之前,先对文件进行 load 加载,框架会自动将变量替换到 html 文件里进行渲染 

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.LoadHTMLFiles("./templates/index.html")r.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html",map[string]interface{}{"title": "前台首页"})})r.Run()
}

http://127.0.0.1:8080/index

请求传值

get查询和动态路由前面已经有示例了,我们看下其他类型的传值。

post获取表单数据

package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.POST("/doAddUser", func(c *gin.Context) {username := c.PostForm("username")password := c.PostForm("password")age := c.DefaultPostForm("age", "20")c.JSON(200, gin.H{"usernmae": username, "password": password, "age": age,})})r.Run()
}

post/get传值绑定到结构体

传值绑定结构体是我们正常开发时最常用的参数解析方式之一了

package mainimport ("fmt""github.com/gin-gonic/gin""net/http"
)type Userinfo struct {Username string `form:"username" json:"user"`Password string `form:"password" json:"password"`
}func main() {r := gin.Default()r.GET("/", func(c *gin.Context) {var userinfo Userinfoif err := c.ShouldBind(&userinfo); err == nil {fmt.Printf("userinfo: %+v\n", userinfo) // userinfo: {Username:zhangsan Password:123456}c.JSON(http.StatusOK, userinfo)} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})r.Run()
}

http://127.0.0.1:8080/?username=zhangsan&password=123456

{"user":"zhangsan","password":"123456"}

同理,POST请求等也可以将请求参数绑定到结构体中

package mainimport ("github.com/gin-gonic/gin""net/http"
)type Userinfo struct {Username string `form:"username" json:"user"`Password string `form:"password" json:"password"`
}func main() {r := gin.Default()r.POST("/doLogin", func(c *gin.Context) {var userinfo Userinfoif err := c.ShouldBind(&userinfo); err == nil {c.JSON(http.StatusOK, userinfo)} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})r.Run()
}

post获取xml数据

一般请求传递 xml 格式数据的遇到的不多,不过也可以试试。

package mainimport ("fmt""github.com/gin-gonic/gin""net/http"
)type Article struct {Title   string `json:"title" xml:"title"`Content string `json:"content" xml:"content"`
}func main() {r := gin.Default()r.POST("/xml", func(ctx *gin.Context) {var article Articleif err := ctx.ShouldBindXML(&article); err == nil {fmt.Printf("article: %+v\n", article)ctx.JSON(http.StatusOK, article)}else {ctx.JSON(http.StatusBadRequest, gin.H {"err": err.Error()})}})r.Run()
}

可以使用 Apifox 发送请求尝试,可以直观看到接口返回的结果

路由分组

路由分组即将相关的路由加上相同的前缀,用以和其他路由进行区分和辨别。

package mainimport ("github.com/gin-gonic/gin"
)func ApiRouter(r *gin.Engine) {apiRouter := r.Group("/api"){apiRouter.GET("/", func(ctx *gin.Context) {ctx.String(200, "api")})apiRouter.GET("articles", func(ctx *gin.Context) {ctx.String(200, "/api/articles")})}
}func main() {r := gin.Default()ApiRouter(r)r.Run()
}

路由分离

路由分离可以将不相关的路由解耦,分离到单独的文件进行维护。

在项目新建文件夹router,然后在router目录下创建apiRouter.go 和adminRouter.go

package router
// apiRouter.go
import "github.com/gin-gonic/gin"func ApiRouter(r *gin.Engine) {apiRouter := r.Group("/api"){apiRouter.GET("/", func(ctx *gin.Context) {ctx.String(200, "api")})apiRouter.GET("articles", func(ctx *gin.Context) {ctx.String(200, "/api/articles")})}
}
package router// adminRouter.go
import ("net/http""github.com/gin-gonic/gin"
)func AdminRouter(r *gin.Engine) {adminRouter := r.Group("/admin"){adminRouter.GET("/", func(ctx *gin.Context) {ctx.String(200, "admin")})adminRouter.GET("list", func(ctx *gin.Context) {ctx.String(http.StatusOK, "admin/list")})}
}

 在main.go中引入路由模块并使用即可

package mainimport ("github.com/gin-gonic/gin""github.com/test/router"
)func main() {// 创建一个默认的路由引擎r := gin.Default()// 引入路由模块router.AdminRouter(r)router.ApiRouter(r)// 启动 HTTP 服务,默认在 0.0.0.0:8080 启动服务r.Run()
}

自定义控制器

当我们的项目比较大的时候有必要对我们的控制器进行分组 , 业务逻辑放在控制器中(有的把业务逻辑处理部分称为 handler)。

新建 controller/api/userController.go

package apiimport "github.com/gin-gonic/gin"func UserIndex(c *gin.Context) {c.String(200, "api UserIndex")
}func UserAdd(c *gin.Context)  {c.String(200, "api UserAdd")
}func UserList(c *gin.Context) {c.String(200, "api UserList")
}
func UserUpdate(c *gin.Context) {c.String(200, "api UserUpdate")
}func UserDelete(c *gin.Context) {c.String(200, "api UserDelete")
}

apiRouter.go

package router
// apiRouter.go
import ("github.com/gin-gonic/gin""github.com/test/controller/api"
)func ApiRouter(r *gin.Engine) {apiRouter := r.Group("/api"){apiRouter.GET("/")apiRouter.GET("/users", api.UserIndex)apiRouter.GET("/users/:id", api.UserList)apiRouter.POST("/users", api.UserAdd)apiRouter.PUT("/users/:id", api.UserUpdate)apiRouter.DELETE("/users", api.UserDelete)}
}

控制器继承

要让控制器可以继承,最好将控制器做成方法的形式(一般默认是函数的形式),这样的话,就可以根据结构体的匿名字段,实现对继承结构体的方法进行很方便的调用。

baseController.go

package apiimport "github.com/gin-gonic/gin"type BaseController struct {
}func (con BaseController) Success(c *gin.Context) {c.String(200, "success")
}func (con BaseController) Error(c *gin.Context) {c.String(200, "failed")
}

userController.go

package apiimport "github.com/gin-gonic/gin"type UserController struct {BaseController
}func (con UserController) UserIndex(c *gin.Context) {// c.String(200, "api UserIndex")con.Success(c)
}func (con UserController) UserAdd(c *gin.Context) {c.String(200, "api UserAdd")
}func (con UserController) UserList(c *gin.Context) {c.String(200, "api UserList")
}
func (con UserController) UserUpdate(c *gin.Context) {c.String(200, "api UserUpdate")
}func (con UserController) UserDelete(c *gin.Context) {c.String(200, "api UserDelete")
}

apiRouter.go

package router
// apiRouter.go
import ("github.com/gin-gonic/gin""github.com/test/controller/api"
)func ApiRouter(r *gin.Engine) {apiRouter := r.Group("/api"){apiRouter.GET("/")apiRouter.GET("/index", api.UserController{}.UserIndex)apiRouter.GET("/users", api.UserController{}.UserList)apiRouter.GET("/users/:id", api.UserController{}.UserList)apiRouter.POST("/users", api.UserController{}.UserAdd)apiRouter.PUT("/users/:id", api.UserController{}.UserUpdate)apiRouter.DELETE("/users", api.UserController{}.UserDelete)}
}

To be continued 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/781905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 系统快速安装 nginx (新手版)

1、安装所需依赖 yum -y install pcre pcre-devel gcc openssl openssl-devel zlib zlib-devel &#xff08;pcre&#xff1a; 包括 perl 兼容的正则表达式库 openssl&#xff1a; 支持安全传输协议https(和财务有关系的请求会走的协议) 创建运行用户、组 useradd -M -…

变分信息瓶颈

变分信息瓶颈和互信息的定义 1 变分信息瓶颈 定义&#xff1a;变分信息瓶颈&#xff08;Variational Information Bottleneck&#xff09;是一种用于学习数据表示的方法&#xff0c;它旨在通过最小化输入和表示之间的互信息来实现数据的压缩和表示学习。这种方法通常用于无监…

Oracle VM(虚拟机)性能监控工具

Oracle VM是一个独立的虚拟化环境&#xff0c;由 Oracle 提供支持和设计&#xff0c;旨在为运行虚拟机提供轻量级、安全的基于服务器的平台。Oracle VM 能够在受支持的虚拟化环境中部署操作系统和应用软件&#xff0c;Oracle VM 将用户和管理员与底层虚拟化技术隔离开来&#x…

ctfshow xxe web373-378

web373 libxml_disable_entity_loader(false)&#xff1a;这行代码用于启用实体加载器&#xff0c;允许加载外部实体。 $xmlfile file_get_contents(php://input)&#xff1a;从输入流中读取XML数据并存储在 $xmlfile 变量中。 $dom->loadXML($xmlfile, LIBXML_NOENT |…

FebHost:意大利.IT域名一张意大利网络名片

.IT域名是意大利的国家顶级域名&#xff0c;对于意大利企业和个人而言,拥有一个属于自己的”.IT”域名无疑是件令人自豪的事。这个被誉为意大利互联网标志性代表的域名,不仅隐含着浓厚的意大利文化特色,还为使用者在当地市场的推广铺平了道路。 对于那些希望在意大利市场建立强…

微信开发者工具接入短剧播放器插件

接入短剧播放插线 申请添加插件基础接入app.jsonapp.jsplayerManager.js数据加密跳转到播放器页面运行出错示例小程序页面页面使用的方法小程序输入框绑定申请添加插件 添加插件:登录微信开发者平台 ——> 设置 ——> 第三方设置 ——> 插件管理 ——> 搜索“短剧…

基于SpringBoot + Vue实现的养老院管理系统设计与实现+毕业论文(12000字)+搭建视频

介绍 养老院管理系统是一款运用软件开发技术设计实现的应用系统&#xff0c;在信息处理上可以达到快速的目的&#xff0c;不管是针对数据添加&#xff0c;数据维护和统计&#xff0c;以及数据查询等处理要求&#xff0c;养老院管理系统都可以轻松应对。 系统包含登录、注册、…

Linux 系统 docker搭建LNMP环境

1、安装nginx docker pull nginx (默认安装的是最新版本) 2、运行nginx docker run --name nginx -p 80:80 -d nginx:latest 备注&#xff1a;--name nginx 表示容器名为 nginx -d 表示后台运行 -p 80:80 表示把本地80端口绑定到Nginx服务端的 80端口 nginx:lates…

【YOLOv5改进系列(9)】高效涨点----使用CAM(上下文增强模块)替换掉yolov5中的SPPF模块

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ CAM模块详细介绍二、2️⃣CAM模块的三种融合模式三、3️⃣如何添加CAM模块3.1 &#x1f393; 添加CAM模块代码3.2 ✨添加yolov5s_CAM.yaml文件3.3 ⭐️修改yolo.py文相关文件 四、4️⃣实验结果4.1 &#x1f39…

Leetcode 82. 删除排序链表中的重复元素 II

给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;[1,2,5] 提示&#xff1a; 链表中节点数目在范围 [0, 300] 内 -100 < Node.…

一些实用的功能函数

1. 【算法】求两个数中&#xff0c;bit位不同的个数&#xff08;在计网那道题中用过&#xff09; 解法&#xff1a;首先把两位数异或&#xff0c;得到的结果&#xff0c;通过自身跟自身-1相与&#xff0c;直到等于0为止 代码如下&#xff1a; int calculateNotSam(int a,int …

uniapp怎么使用接口返回的iconfont图标

uniapp怎么使用接口返回的iconfont图标 首先在你的项目中添加该图标&#xff0c;名称要对应 实际应用 item.ICONFONT_NAME“tools”; item.ICONFONT_COLOR“FA5151”; <view class"iconfont" :class"icon-item.ICONFONT_NAME" :color"item.ICON…

Kubernetes Pod深度解析:构建可靠微服务的秘密武器(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Kubernetes航线图&#xff1a;从船长到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Kubernetes概述 2、Pod概述 二、Po…

输出单链表倒数第K个结点值

方法一&#xff1a; 两次遍历链表。第一次遍历&#xff0c;计算链表长度&#xff0c;然后计算链表倒数第m个结点的正数位置k&#xff0c;判断位置是否合法&#xff0c;如果不合法&#xff0c;输出NOT FOUND&#xff0c;否则&#xff0c;进行第二次遍历链表&#xff0c;查找链表…

手写SpringBoot(三)之自动配置

系列文章目录 手写SpringBoot&#xff08;一&#xff09;之简易版SpringBoot 手写SpringBoot&#xff08;二&#xff09;之动态切换Servlet容器 手写SpringBoot&#xff08;三&#xff09;之自动配置 手写SpringBoot&#xff08;四&#xff09;之bean动态加载 手写SpringBoot…

企业培训系统功能介绍

在当今知识经济时代&#xff0c;企业的竞争力在很大程度上取决于员工的专业能力和综合素质。为了适应不断变化的市场需求和技术进步&#xff0c;企业需要对员工进行持续有效的培训。一个高效的企业培训系统对企业人才培训至关重要。以下介绍一下企业培训系统的主要功能&#xf…

电脑文件msvcp120.dll丢失的解决方法详细分析,找多种靠谱方法修复

遇到msvcp120.dll文件丢失的问题实际上不算罕见&#xff0c;这往往是由于我们频繁使用电脑而导致的意外删除&#xff0c;或者是电脑受到病毒感染。当这类情况发生时&#xff0c;msvcp120.dll文件可能会被错误地移除或损坏&#xff0c;这便需要我们去进行修复。接下来&#xff0…

【系统架构师】-第18章-安全架构设计

(1)信息泄露&#xff1a;信息被泄露或透露给某个非授权的实体。 (2)破坏信息的完整性&#xff1a;数据被非授权地进行增删、修改或破坏而受到损失。 (3)拒绝服务&#xff1a;对信息或其他资源的合法访问被无条件地阻止。 (4)非法使用(非授权访问):某一资源被某个非授权的人或…

FA模型切换Stage模型组件切换之ServiceAbility切换DataAbility切换

ServiceAbility切换 FA模型中的ServiceAbility对应Stage模型中的ServiceExtensionAbility。Stage模型下的ServiceExtensionAbility为系统API&#xff0c;只有系统应用才可以创建。因此&#xff0c;FA模型的ServiceAbility的切换&#xff0c;对于系统应用和三方应用策略有所不同…

实践笔记-harbor搭建(版本:2.9.0)

harbor搭建 1.下载安装包&#xff08;版本&#xff1a;2.9.0&#xff09;2.修改配置文件3.安装4.访问harbor5.可能用得上的命令: 环境&#xff1a;centos7 1.下载安装包&#xff08;版本&#xff1a;2.9.0&#xff09; 网盘资源&#xff1a;https://pan.baidu.com/s/1fcoJIa4x…