go从0到1项目实战体系二十二:gin构建一个http server

1. 构建一个http server:

// api.test.com/topic/main.go:
type Topic struct {Id int           // 如果写成小写的,不能访问,因为是私有的.Title string
}
func main() {data := make(map[string]interface{})data["name"] = "david"data["age"] = 12// 默认路由router := gin.Default()router.GET("/", func(context *gin.Context) {context.Writer.Write([]byte("hello"))                                 // (1)// context.JSON(http.StatusOK, data)                                  // (2)// context.JSON(http.StatusOK, gin.H{"name": "daivd", "age": 12})     // (3)// context.JSON(http.StatusOK, Topic{100, "话题标题"})                 // (4)})router.Run()
}

(1). 返回text/plain格式的结果:hello

HTTP/1.1 200 OK
Date: Fri, 01 Nov 2019 04:09:18 GMT
Content-Length: 5
Content-Type: text/plain; charset=utf-8

(2). 返回json的格式:{“age”:12, “name”:“david”}

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Mon, 04 Nov 2019 11:00:06 GMT
Content-Length: 25

(3). 返回如上json的格式:{“age”:12, “name”:“david”}

# 1. gin.H{}底层实现方案:
// H is a shortcut for map[string]interface{}
type H map[string]interface{}# 2. 模拟实现:
type M map[string]interface{}. make的形式:m := make(M)m["name"] = "david"# 在使用map,需要先make,make的作用就是给map分配数据空间②. 直接赋值:map[string]interface{}{"name": "daivd"}. M就相当于map[string]interface{}的简写:M{"name": "daivd"}

(4). 对象返回如上json的格式:{“Id”:100, “Title”:“话题标题”}


2. API的URL规则设计:

2.1 httprouter库:

①. gin的路由使用的是httprouter库.
②. 不支持正则、不支持固定路径和参数路径.
③. 保证了性能,但功能不强大.

2.2 API设计建议:

(1). 常规上的路由:

GET /topic/{topic_id}:获取帖子明细
GET /topic/{user_name}:获取用户发布的帖子列表
GET /topic/top:获取最热帖子列表

(2). 建议改进路由规则:

①. 最好API前面加上版本:GET /v1/topic/:id②. 尽可能使用复数的语义化名词:GET /v1/topics③. 使用GET参数规划数据展现规则:GET /v1/users                  // 显示全部用户GET /v1/users?limit=10         // 显示10条用户GET /v1/topics?username=xx     // 显示xx的帖子

3.3 增加其它路由:

api.test.com/topic/main.go:

router := gin.Default()
router.GET("/v1/topics/:topic_id", func(context *gin.Context) {context.String(http.StatusOK, "获取%s的帖子", context.Param("topic_id"))
})
router.GET("/v1/topics", func(context *gin.Context) {if context.Query("username") == "" {context.String(http.StatusOK, "获取所有帖子")} else {context.String(http.StatusOK, "获取%s所有帖子", context.Query("username"))}
})
router.Run()

注:

①. 以下几条路由不允许:router.GET("/topic/:id")router.GET("/topic/topic")router.GET("/topic/topic/:username")②. 报错:panic: 'topic' in new path '/topic/topic' conflicts with existing wildcard ':topic_id' in existing prefix '/:topic_id'③. context.Param可以获取"/v1/topics/:topic_id"中以冒号的形式设置url参数topic_id.④. context.Query可以当get传参的时候,url上显示的参数.

3.4 路由分组:

(1). api.test.com/topic/main.go:

import "topic.test.com/src"  // moduel/文件名
func main() {router := gin.Default()// 定义一个路由分组v1 := router.Group("/v1/topics")// {}不是强关联,只是为了美观,做代码切割,不写也可以,有作用域的区别{// 什么都不写,表示与组的路由是一致的(GET /v1/topics)v1.GET("", src.GetList)  // 将业务代码分离出去v1.GET("/:topic_id", func(context *gin.Context) {context.String(http.StatusOK, "获取%s的帖子", context.Param("topic_id"))})// 在这个下面所有定义的路由都需要鉴权v1.Use(src.MustLogin()){v1.POST("", src.AddTopic)}}router.Run()
}:. 如果src.GetList(),不想写src的话.需要这样引入  =>  . "topic.test.com/src". 不能写src.GetList(),否则是表示执行函数得到的结果.. 如果想写src.GetList(),则需要改造如下:func GetList2() gin.HandlerFunc {return func (c *gin.Context) {//}}. v1.Use的参数为HandlerFunc,所以是执行函数返回结果.. 为了美观,可以在路由上加一个{}代码块(代码块有作用域),不是强关联,只是为了美观.

(2). api.test.com/topic/src/TopicDao.go:

src是所有业务代码

func MustLogin() gin.HandlerFunc {return func (c *gin.Context) {if _, status := c.GetQuery("token");!status {c.String(http.StatusUnauthorized, "授权失败")c.Abort()  // 没有的话,会继续往下执行} else {c.Next()}}
}
func GetList(c *gin.Context) {// if c.Query("username") == "" {//  	c.String(http.StatusOK, "获取所有帖子")// } else {//  	c.String(http.StatusOK, "获取%s所有帖子", c.Query("username"))// }// get参数校验query := TopicQuery{}err := c.BindQuery(&query)  // 是BindQueryif err != nil {c.JSON(500, "参数错误")  // 自动报一个400 Bad Request的错误,写成500也是400} else {c.JSON(http.StatusOK, query)}
}
func AddTopic(c *gin.Context) {// c.JSON(http.StatusOK, CreateTopic(1, "PHP"))// post参数校验query := Topic{}err := c.BindJSON(&query)  // 是BindJSONif err != nil {c.JSON(500, "参数错误")} else {c.JSON(http.StatusOK, query)}
}:. Dao层操作数据库实体、redis实体.. 路由测试:POST localhost:8080/v1/topics  => 结果是:授权失败POST localhost:8080/v1/topics?token=123  => 结果是:{ "id": 1, "title": "PHP" }如果没有json映射字段则返回:{ "TopicId": 1, "TopicTitle": "PHP" }. 参数绑定Model:a. GetList中,如果参数有username、page、pagesize等,if来判断的话,非常繁琐.b. 可以将get参数绑定(get参数映射为一个模型).c. 很多流行框架支持参数绑定Model(传过来的参数与model进行绑定).. GET localhost:8080/v1/topics?username=david&page=1&pagesize=10=> 如果TopicQuery struct中没有form字段会是{ "username": "", "page": 0, "pagesize": 0 }localhost:8080/v1/topics?username=david&page=1=> { "username": "david", "page": 1, "pagesize": 0 }localhost:8080/v1/topics?username=david&page=1&pagesize=10=> { "username": "david", "page": 1, "pagesize": 10 }localhost:8080/v1/topics?username=david&pagesize=10=> 参数错误localhost:8080/v1/topics?username=david&page=0=> 参数错误,page为0localhost:8080/v1/topics?username=david&page=""=> 参数错误,page为""

(3). api.test.com/topic/src/TopicModel.go:

package src
type Topic struct {TopicId int `json:"id"`  // json反射的映射字段TopicTitle string `json:"title" binding:"min=4,max=20"`  // 在4和20字之间,中英文都是一样TopicShortTitle string `json:"stitle" binding:"requried,nefield=TopicTitle"`  // 不能与TopicTitle一样UserIP string `json:"ip" binding:"ipv4"`TopicScore int `json:"score" binding:"omitempty,gt=5"`  // 可以不填,填了就大于5TopicUrl string `json:"url" binding:"omitempty,topicurl"`
}
func CreateTopic (id int, title string) Topic {return Topic{id, title}
}
// query参数绑定
type TopicQuery struct {UserName string `json:"username" form:"username"`Page int `json:"page" form:"page" binding:"required"`PageSize int `json:"pagesize" form:"pagesize"`
}:. form决定了绑定query参数的key到底是什么.没写form,则不会绑定.. 内置验证器是第三方库github.com/go-playground/validator

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

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

相关文章

TwIST算法MALTLAB主程序详解

TwIST算法MALTLAB主程序详解 关于TwIST算法的具体原理可以参考: 链接: https://ieeexplore.ieee.org/abstract/document/4358846 链接: https://blog.csdn.net/jbb0523/article/details/52193209 该算法的MATLAB源代码: 链接: http://www.lx.it.pt/~bi…

tcp和udp协议分别是什么意思有什么区别?

TCP(传输控制协议)和UDP(用户数据报协议)是两种网络传输协议,它们在网络通信中有一些关键的区别。 连接性: TCP: 提供面向连接的服务。在通信之前,需要建立连接,数据传输…

Node.js(二)-模块化

1. 模块化的基本概念 1.1 什么是模块化 模块化是指解决一个复杂问题时,自顶向下逐层将系统拆分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。 1.2 编程领域中的模块化 编程领域中的模块化,就是遵守固定的规则&…

48V转12V 300mA降压芯片,60V耐压、0.6A稳压芯片带ECO模式-AH590L

AH590L是一种48V转12V 300mA降压芯片,具有60V耐压、0.6A稳压电流的特点,并且还带有ECO模式,是一种理想的开关电源解决方案。 AH590L是PWM模式 DC/DC降压转换器。TEL:l86*4884*3702*宽输入电压范围4至60V适用于工业领域的广泛应用…

有意思、好用的免费API分享

Facebook Games Services - Facebook Games Services 为游戏开发者提供了各种服务, 包括(但不限于) 成就 API, 分数 API, 应用通知, 请求, 游戏养成和 Facebook SDK for Unity.Google Play Games Services - Google Developers Games 网站提供了各种 API, SDK 和服务, 包括(但不…

AI安全综述

1、引言 AI安全这个话题,通常会引伸出来图像识别领域的对抗样本攻击。下面这张把“熊猫”变“猴子”的攻击样例应该都不陌生,包括很多照片/视频过人脸的演示也很多。 对抗样本的研究领域已经具备了一定的成熟性,有一系列的理论来论述对抗样本…

解决jquery-1.11.0.js安全漏洞

摘要:这个文件被扫出安全漏洞有XSS攻击等 ,其中一个比较著名的漏洞是在JQuery 1.6.2版本中发现的。该漏洞被称为”attrFn"漏洞,它允许攻击者通过特殊构造的代码执行任意的JavaScript代码。 一、统一解决方式: jQuery官网 官…

javafx实现复杂统计图绘画

JavaFX 是一个用于创建富互联网应用程序 (Rich Internet Applications) 的软件平台,可以用于创建各种图形和图表。下面是一个示例代码,演示如何使用 JavaFX 绘制复杂的统计图。 import javafx.application.Application; import javafx.collections.FXCollections; import ja…

one wire(单总线)FPGA代码篇

一.引言 单总线(OneWire)是一种串行通信协议,它允许多个设备通过一个单一的数据线进行通信。这个协议通常用于低速、短距离的数字通信,特别适用于嵌入式系统和传感器网络。 二.one wire通信优点缺点 优点: 单一数据线…

Unity程序向Web服务器发送数据

Unity程序向Web服务器发送数据 一、介绍二、HTTP协议三、新建Unity工程,创建脚本1.新建Unity工程,创建脚本WebManager.cs,将其指定给场景中的任意游戏体。2.在WebManager.cs中添加一个m_info属性和OnGUI函数显示UI: 四、GET请求在…

npm使用详解(好吧好吧是粗解)

目录 npm是什么? npm有什么用? npm安装 在 Windows 上 在 macOS 上 在 Linux 上(使用 apt 包管理器为例) 验证 npm 安装成功: npm使用 1. 初始化项目: 2. 安装和管理依赖: 3. 查看和…

【DataV】DataV组件库——更新数据视图不更新

参考文章:dataV组件库——改变数据视图不主动刷新 问题: 拿到后端数值就直接赋值了,但是视图(页面)没有更新。 解决: 官方文档介绍dataV里面的组件props均未设置deep监听,刷新props时&#xf…

一个利用摸鱼时间背单词的软件

大家好,我是 Java陈序员。 最近进入了考试季,各种考试,英语四六级、考研、期末考等。不知道大家的英语四六级成绩怎么样呢? 记得大学时,英语四级都是靠高中学习积累的老本才勉强过关。 而六级则是考了多次&#xff…

20231224解决outcommit_id.xml1 parser error Document is empty的问题

20231224解决outcommit_id.xml1 parser error Document is empty的问题 2023/12/24 18:13 在开发RK3399的Android10的时候,出现:rootrootrootroot-X99-Turbo:~/3TB/Rockchip_Android10.0_SDK_Release$ make installclean PLATFORM_VERSION_CODENAMEREL…

静态HTTP的常见问题和解决方法

大家好,欢迎来到今天的“静态HTTP大讲堂”!今天我们要聊聊静态HTTP的常见问题和解决方法。别小看这些问题哦,它们就像是那些顽皮的小妖精,时不时地给你的网站搞点恶作剧。不过别担心,有我在,这些小妖精都得…

推荐一款好用的免费图片转换工具bmp转png工具bmp2png

推荐一款好用的免费图片转换工具bmp转png工具bmp2png 写这个工具是因为要使用传奇的部分素材在COCOS2DX使用,但是COCOS2DX不支持BMP如果直接将BMP转换到PNG的话,网上找到的工具都不支持透明色转换。难道要用PS一个一个抠图吗?要累死所以写了…

HBase 超大表迁移、备份、还原、同步演练手册:全量快照 + 实时同步(Snapshot + Replication)不停机迁移方案

博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,京东购书链接:https://item.jd.com/12677623.html,扫描左侧二维…

如何选择适合业务的负载均衡策略?

在分布式系统的高可用设计中,负载均衡非常关键,我们知道,分布式系统的特性之一就是支持快速扩展,那么集群扩展之后,服务请求如何从服务器列表中选择合适的一台呢?这就需要依赖负载均衡策略。 负载均衡在处…

免 费 搭 建 小程序商城,打造多商家入驻的b2b2c、o2o、直播带货商城

在数字化时代,电商行业正经历着前所未有的变革。鸿鹄云商的saas云平台以其独特的架构和先进的理念,为电商行业带来了全新的商业模式和营销策略。该平台涉及多个平台端,包括平台管理、商家端、买家平台、微服务平台等,涵盖了pc端、…

项目执行常用的ChatGPT通用提示词模板

项目启动与准备:如何确保项目按计划启动,并为项目执行做好充分准备? 任务分配与执行:如何合理分配任务,确保项目团队成员明确各自的责任和目标? 进度监控与调整:如何实时监控项目进度&#xf…