golang gin入门

gin是个小而精的web开发框架
官方文档

安装

go get -u github.com/gin-gonic/gin
最简单的起手代码
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/ping", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})r.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
get、post、put等http方法
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.GET("/someGet", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.POST("/somePost", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.PUT("/somePut", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.DELETE("/someDelete", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.PATCH("/somePatch", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.HEAD("/someHead", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.OPTIONS("/someOptions", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
路由分组
package mainimport ("github.com/gin-gonic/gin"
)func goodList(c *gin.Context) {c.JSON(200, gin.H{"message": "goodList",})
}
func goodsDetail(c *gin.Context) {c.JSON(200, gin.H{"message": "goodsDetail",})
}
func createGoods(c *gin.Context) {c.JSON(200, gin.H{"message": "createGoods",})
}
func main() {router := gin.Default()goodsGroup := router.Group("/goods"){goodsGroup.GET("/list", goodList)goodsGroup.GET("/1", goodsDetail)goodsGroup.GET("/add", createGoods)}router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
带参数的url
package mainimport ("github.com/gin-gonic/gin"
)func goodList(c *gin.Context) {c.JSON(200, gin.H{"message": "goodList",})
}
func goodsDetail(c *gin.Context) {id := c.Param("id")action := c.Param("action")c.JSON(200, gin.H{"message": "goodsDetail","id":      id,"action":  action,})
}
func createGoods(c *gin.Context) {c.JSON(200, gin.H{"message": "createGoods",})
}
func main() {router := gin.Default()goodsGroup := router.Group("/goods"){goodsGroup.GET("", goodList)goodsGroup.GET("/:id/:action", goodsDetail)// goodsGroup.GET("/:id/*action", goodsDetail)goodsGroup.POST("", createGoods)}router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}
获取路由分组的参数
package mainimport ("net/http""github.com/gin-gonic/gin"
)type Person struct {ID   string `uri:"id" binding:"required,uuid"`Name string `uri:"name" binding:"required"`
}func main() {router := gin.Default()router.GET("/:name/:id", func(c *gin.Context) {var person Personif err := c.ShouldBindUri(&person); err != nil {c.Status(404)return}c.JSON(http.StatusOK, gin.H{"name": person.Name,"id":   person.ID,})})router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}

http://localhost:8080/sd1/8bebdad9-2829-4849-a011-c19128061822

获取get和post参数

get、post和get&post

package mainimport ("fmt""net/http""github.com/gin-gonic/gin"
)func welcome(c *gin.Context) {firstName := c.DefaultQuery("firstname", "bobby")lastName := c.Query("lastname")c.JSON(http.StatusOK, gin.H{"first_name": firstName,"last_name":  lastName,})
}func formPost(c *gin.Context) {message := c.PostForm("message")nick := c.DefaultPostForm("nick", "anonymous")c.JSON(http.StatusOK, gin.H{"message": message,"nick":    nick,})
}func main() {router := gin.Default()//get请求router.GET("/welcome", welcome)//post请求router.POST("/form", formPost)//post & getrouter.POST("/postsd", func(c *gin.Context) {id := c.Query("id")page := c.DefaultQuery("page", "0")name := c.PostForm("name")message := c.PostForm("message")fmt.Printf("id: %s,page: %s,name: %s,message: %s", id, page, name, message)})router.Run() // listen and serve on 0.0.0.0:8080// r.Run(":8083") // listen and serve on 0.0.0.0:8080
}

在这里插入图片描述

http://localhost:8080/welcome?firstname=dlkjf&lastname=sdfljk

JSON、ProtoBuf 渲染

json渲染、Prootobuf渲染和purejson渲染

package mainimport ("net/http""GolangStudy/Introduction/proto""github.com/gin-gonic/gin"
)func moreJSON(c *gin.Context) {var msg struct {Name    string `json:"user"`Message stringNumber  int}msg.Name = "bobby"msg.Message = "测试json"msg.Number = 20c.JSON(http.StatusOK, msg)
}
func returnProto(c *gin.Context) {user := &proto.Teacher{Name:   "bobby",Course: []string{"python", "go", "java"},}c.ProtoBuf(http.StatusOK, user)
}
func main() {router := gin.Default()router.GET("/moreJSON", moreJSON)router.GET("/someProtoBuf", returnProto)router.GET("/pureJSON", func(c *gin.Context) {c.PureJSON(200, gin.H{"html": "<b>Hello, world!</b>",})})router.Run()
}
表单验证

Gin使用 go-playground/validator 验证参数
文档

package mainimport ("fmt""net/http""github.com/gin-gonic/gin"
)// 绑定为json
type LoginForm struct {User     string `form:"user" json:"user" xml:"user"  binding:"required,min=3,max=10"` //min最短长度,max最大长度Password string `form:"password" json:"password" xml:"password" binding:"required"`
}func main() {router := gin.Default()router.POST("/loginJSON", func(c *gin.Context) {var loginForm LoginFormif err := c.ShouldBind(&loginForm); err != nil {fmt.Println(err.Error())c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}c.JSON(http.StatusOK, gin.H{"msg": "登录成功",})})router.Run()
}

在这里插入图片描述

注册表单的验证
package mainimport ("fmt""net/http""github.com/gin-gonic/gin"
)// 绑定为json
type LoginForm struct {User     string `form:"user" json:"user" xml:"user"  binding:"required,min=3,max=10"` //min最短长度,max最大长度Password string `form:"password" json:"password" xml:"password" binding:"required"`
}type SignUpForm struct {Age        uint8  `json:"age" binding:"gte=1,lte=130"`Name       string `json:"name" binding:"required,min=3"`Email      string `json:"email" binding:"required,email"`Password   string `json:"password" binding:"required"`RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}func main() {router := gin.Default()router.POST("/loginJSON", func(c *gin.Context) {var loginForm LoginFormif err := c.ShouldBind(&loginForm); err != nil {fmt.Println(err.Error())c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}c.JSON(http.StatusOK, gin.H{"msg": "登录成功",})})router.POST("/signup", func(c *gin.Context) {var signForm SignUpFormif err := c.ShouldBind(&signForm); err != nil {fmt.Println(err.Error())c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}c.JSON(http.StatusBadRequest, gin.H{"msg": "注册成功",})})router.Run()
}

在这里插入图片描述

表单验证错误翻译成中文
package mainimport ("fmt""net/http""reflect""strings""github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding""github.com/go-playground/locales/en""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator""github.com/go-playground/validator/v10"en_translations "github.com/go-playground/validator/v10/translations/en"zh_translations "github.com/go-playground/validator/v10/translations/zh"
)// 绑定为json
type LoginForm struct {User     string `form:"user" json:"user" xml:"user"  binding:"required,min=3,max=10"` //min最短长度,max最大长度Password string `form:"password" json:"password" xml:"password" binding:"required"`
}type SignUpForm struct {Age        uint8  `json:"age" binding:"gte=1,lte=130"`Name       string `json:"name" binding:"required,min=3"`Email      string `json:"email" binding:"required,email"`Password   string `json:"password" binding:"required"`RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}func removeTopStruct(fileds map[string]string) map[string]string {rsp := map[string]string{}for field, err := range fileds {rsp[field[strings.Index(field, ".")+1:]] = err}return rsp
}
func InitTrans(locale string) (err error) {//修改gin的validator引擎属性,实现定制if v, ok := binding.Validator.Engine().(*validator.Validate); ok {//注册一个获取json的tag的自定义方法v.RegisterTagNameFunc(func(fld reflect.StructField) string {name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]if name == "-" {return ""}return name})zhT := zh.New() //中文翻译器enT := en.New() //英文翻译器//第一个是备用的,后面的是支持的语言环境uni := ut.New(enT, zhT, enT)trans, ok = uni.GetTranslator(locale)if !ok {return fmt.Errorf("uni.GetTranslator(%s)", locale)}switch locale {case "en":en_translations.RegisterDefaultTranslations(v, trans)case "zh":zh_translations.RegisterDefaultTranslations(v, trans)default:en_translations.RegisterDefaultTranslations(v, trans)}return}return
}var trans ut.Translatorfunc main() {if err := InitTrans("zh"); err != nil {fmt.Println("初始化翻译器错误")return}router := gin.Default()router.POST("/loginJSON", func(c *gin.Context) {var loginForm LoginFormif err := c.ShouldBind(&loginForm); err != nil {errs, ok := err.(validator.ValidationErrors)if !ok {c.JSON(http.StatusOK, gin.H{"msg": err.Error(),})} else {c.JSON(http.StatusBadRequest, gin.H{"error": removeTopStruct(errs.Translate(trans)),})}fmt.Println(err.Error())return}c.JSON(http.StatusOK, gin.H{"msg": "登录成功",})})router.POST("/signup", func(c *gin.Context) {var signForm SignUpFormif err := c.ShouldBind(&signForm); err != nil {errs, ok := err.(validator.ValidationErrors)if !ok {c.JSON(http.StatusOK, gin.H{"msg": err.Error(),})} else {c.JSON(http.StatusBadRequest, gin.H{"error": removeTopStruct(errs.Translate(trans)),})}fmt.Println(err.Error())return}c.JSON(http.StatusBadRequest, gin.H{"msg": "注册成功",})})router.Run()
}

在这里插入图片描述

中间件

gin.New()可以添加中间件;gin.Default()默认启动方式,包含 Logger、Recovery 中间件
添加中间件

package mainimport ("fmt""net/http""time""github.com/gin-gonic/gin"
)func MyLogger() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()c.Set("example", "123456")//让原本该执行的逻辑继续执行c.Next()end := time.Since(t)fmt.Printf("耗时:%V\n", end)status := c.Writer.Status()fmt.Println("状态", status)}
}
func main() {router := gin.New()//使用logger和recovery中间件router.Use(MyLogger())router.GET("/ping", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.Run()
}

通过c.abort()实现中止中间件的执行(通过return是不能终止的,因为中间件都存储在中间件队列中,当前中间的中止会继续调用后续的中间件,直到调用完成。c.abort()会将中间件队列的索引值改为math.MaxInt8/2实现不调用后续中间件)

package mainimport ("fmt""net/http""time""github.com/gin-gonic/gin"
)func MyLogger() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()c.Set("example", "123456")//让原本该执行的逻辑继续执行c.Next()end := time.Since(t)fmt.Printf("耗时:%V\n", end)status := c.Writer.Status()fmt.Println("状态", status)}
}
func TokenRequired() gin.HandlerFunc {return func(c *gin.Context) {var token stringfor k, v := range c.Request.Header {if k == "X-Token" {token = v[0]}fmt.Println(k, v, token)}if token != "bobby" {c.JSON(http.StatusUnauthorized, gin.H{"msg": "未登录",})c.Abort()}c.Next()}
}
func main() {router := gin.New()//使用logger和recovery中间件router.Use(TokenRequired())router.GET("/ping", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "pong",})})router.Run()
}
gin加载html文件

在这里插入图片描述
html路径可以使用绝对路径和相对路径(推荐),使用相对路径需要先go build后运行,主要是因为直接通过编译器执行生成的可执行文件放置于系统的临时文件夹中并不抱存在当前项目的路径下,所以会出现找不到html文件。

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()//制定加载好相对路径router.LoadHTMLFiles("templates/index.tmpl")router.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "mooc",})})router.Run()
}

加载多html文件

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()//制定加载好相对路径//加载二级目录router.LoadHTMLGlob("templates/**/*")// router.LoadHTMLFiles("templates/index.tmpl", "templates/goods.html")router.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "mooc",})})router.GET("/goods/list", func(c *gin.Context) {c.HTML(http.StatusOK, "goods/list.html", gin.H{"name": "微服务开发",})})router.GET("/users/list", func(c *gin.Context) {c.HTML(http.StatusOK, "users/list.html", gin.H{"name": "微服务开发",})})router.Run()
}
优雅退出

自定义监听结束信号,方便完成关闭服务器等后续操作

package mainimport ("fmt""net/http""os""os/signal""syscall""github.com/gin-gonic/gin"
)func main() {//优雅推出,当我们关闭程序后需要做的处理//微服务 启动之前或者启动之后必须做一件事:将当前的ip地址和端口号注册到注册中心//我们当前的服务停止之后并没有告知注册中心router := gin.Default()router.GET("/", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "pong",})})go func() {router.Run()}()//接受信号quit := make(chan os.Signal)//syscall.SIGINT ctrl+csignal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)<-quit//处理后续的逻辑fmt.Println("关闭server中。。。")fmt.Println("注册服务。。。")
}

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

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

相关文章

openpnp - 图像传送方向要在高级校正之前设置好

文章目录 openpnp - 图像传送方向要在高级校正之前设置好笔记图像传送方向的确定END openpnp - 图像传送方向要在高级校正之前设置好 笔记 图像传送方向和JOG面板的移动控制和实际设备的顶部摄像头/底部摄像头要一致&#xff0c;这样才能和贴板子时的实际操作方向对应起来。 …

大数据新视界 --大数据大厂之 从 Druid 和 Kafka 到 Polars:大数据处理工具的传承与创新

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【Vue】vue-admin-template项目搭建

准备 node环境 node&#xff1a;v16.12.0npm&#xff1a;8.1.0 vue-element-admin下载 官网&#xff1a;https://panjiachen.github.io/vue-element-admin-site/guide/ 我这边下载的是4.4.0版本的&#xff0c;使用其他版本可能会因为所需要的node和npm版本过低或过高导致异常…

【包教包会】2D图片实现3D透视效果(支持3.x、支持原生、可合批)

将去年写的SpriteFlipper从2.x升级到3.x。 如果需要2.x版本或需要了解算法思路&#xff0c;请移步&#xff1a;https://blog.csdn.net/weixin_42714632/article/details/136745051 优化功能&#xff1a;可同时绕X轴和Y轴旋转&#xff0c;两者效果会叠加。 完美适配Web、原生…

Gridview配置数据源--信任服务器证书

目录 背景过程Gridview配置数据源GridView与数据源&#xff1a;数据库连接与安全&#xff1a;信任服务器证书&#xff1a;配置信任服务器证书&#xff1a;注意事项&#xff1a; 生成连接字符串程序运行报错问题解决 总结 背景 Gridview配置数据源之后&#xff0c;程序报错 过…

k8s的pod的管理和优化

资源管理介绍 在kubernetes中&#xff0c;所有的内容都抽象为资源&#xff0c;用户需要通过操作资源来管理kubernetes。 kubernetes的本质上就是一个集群系统&#xff0c;用户可以在集群中部署各种服务 所谓的部署服务&#xff0c;其实就是在kubernetes集群中运行一个个的容器…

C++ | Leetcode C++题解之第456题132模式

题目&#xff1a; 题解&#xff1a; class Solution { public:bool find132pattern(vector<int>& nums) {int n nums.size();vector<int> candidate_i {nums[0]};vector<int> candidate_j {nums[0]};for (int k 1; k < n; k) {auto it_i upper_…

动态规划基础一>面试题 08.01. 三步问题

1.题目&#xff1a; 2.解析&#xff1a; 代码&#xff1a; public int waysToStep(int n) {/**1.创建dp表2.初始化3.填表4.返回值*/int MOD (int)1e9 7;//注意不能超出int范围&#xff0c;每做一次操作要取模//处理边界情况if(n 1 || n 2) return n;if(n 3) return 4;//1…

【Kubernetes】常见面试题汇总(五十七)

目录 125. K8S 创建服务 status 为 ErrlmagePull&#xff1f; 126.不能进入指定容器内部&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。 题目 …

Django学习笔记二:数据库操作详解

Django框架提供了一个功能强大的ORM&#xff08;对象关系映射&#xff09;系统&#xff0c;使得开发者可以使用Python代码来操作数据库&#xff0c;而无需编写复杂的SQL语句。以下是Django数据库操作的一些基本概念和方法&#xff1a; 模型定义 在Django中&#xff0c;模型是…

两数相除(c语言)

1.//给你两个整数&#xff0c;被除数 dividend 和除数 divisor。将两数相除&#xff0c;要求 不使用 乘法、除法和取余运算。 //整数除法应该向零截断&#xff0c;也就是截去&#xff08;truncate&#xff09;其小数部分。 // 例如&#xff0c;8.345 将被截断为 8 &#xff0c;…

内网穿透工具ngrok

写作背景 最近在公司内购淘了个MAC电脑&#xff0c;想当个Linux服务器起Docker搭建环境用&#xff0c;现在问题是如何在公网上能访问到MAC这个机器上的资源。 之前写了一篇文章Mac当作云服务器&#xff0c;你真的会搞吗 最近想重启一下这台老伙计了&#xff0c;发现ngrok还是…

视频加字幕用什么软件最快?12款工具快速添加字幕!

对于大多数同学来讲&#xff0c;剪辑中比较头疼的就是如何给视频加字幕和唱词啦&#xff0c;特别是用Pr或者FCXP等专业剪辑软件&#xff0c;加字幕也是特别费时的&#xff0c;哪怕是有批量添加的功能orz... 虽然关于这方面的内容已经很多啦&#xff0c;但是真正全面的内容还特…

VTC视频时序控制器,TPG图像测试数据发生器,LCD驱动——FPGA学习笔记19

详情可以见LCD篇 LCD彩条显示——FPGA学习笔记10_依次显示红绿蓝三个通道-CSDN博客 一、VTC简介 Video Timing Controller 缩写 VTC 是我们在所有涉及 FPGA 图像、 FPGA 视频类方案中经常用到的一种用于产生视频时序的控制器。 本课以 VGA 为切入点&#xff0c; 学习视频传输…

[Linux]:线程(三)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;Linux学习 贝蒂的主页&#xff1a;Betty’s blog 1. POSIX 信号量 1.1 信号量的概念 为了解决多执行流访问临界区&#xff0c…

基于SpringBoot+Vue的酒店客房管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

[SAP ABAP] 程序调用

示例数据 学生表(ZDBT_STU_437) 程序&#xff1a; Z437_TEST_20241006 代码如下所示 REPORT Z437_TEST_20241006.* 创建跟表或结构同名的工作区 TABLES: zdbt_stu_437.SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.PARAMETERS: p_1 TYPE c LENGTH 4.SELECT-O…

Kali或Debian系统安装JDK1.8保姆级教程

一、下载JDK1.8 先到Oracle的官网下载JDK1.8 Java Archive | Oraclehttps://www.oracle.com/java/technologies/downloads/archive/Java Archive Downloads - Java SE 8

CUDA、Pytorch、Pycharm的安装与配置

文章目录 一、CUDA安装1.检查英伟达驱动支持的最高CUDA版本 二、Pytorch的安装与环境配置1.选择是下载CPU版本还是GPU版本2.上Pytorch官网找到安装命令3.运行指令(1)CPU版本(2)GPU版本 4.验证5.安装其他所需模块(0)安装torch(1)安装Matplotlib(2)安装 pillow&#xff08;可能an…

OSPF的不规则区域

1.远离骨干非骨干区域 2.不连续骨干 解决方案 tunnel ---点到点GRE 在合法与非ABR间建立隧道&#xff0c;然后将其宣告于OSPF协议中&#xff1b; 缺点&#xff1a;1、周期和触发信息对中间穿越区域造成资源占用&#xff08;当同一条路由来自不同区域&#xff0c;路由器会先…