学习gin| 青训营笔记

80 阅读5分钟

这是我参与「第五届青训营 」笔记创作活动的第12天

Gin的安装使用

安装gin:go get -u github.com/gin-gonic/gin

go get的本质就是git clone

关于web

  • web是基于HTTP协议进行交互的应用网络
  • web就是通过使用浏览器/APP访问的各种资源
    • 浏览器/APP向服务器发起请求(request),然后服务器再发出对应的相应(response)

gin框架初识

package main

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

func sayHello(c *gin.Context) { //放在HTTP请求方法里面的函数,一定要有 *gin.Context类型的参数
	c.JSON(200, gin.H{
		"msg": "hello golang!",
	})
}

func main() {
	//创建一个服务,返回默认的路由引擎
	ginServer := gin.Default()
	ginServer.Use(favicon.New("./favicon.ico"))
	//链接数据库的代码

	//访问地址,处理我们的请求	Request Response
	// ginServer.GET("/hello" /*这个是相对路径,relativePath*/, func(context *gin.Context) { /*这是个匿名函数*/
	// 	context.JSON(200, gin.H{"msg": "死歪哥祯的太差"})
	// })
	ginServer.GET("/hello" /*这个是相对路径,relativePath*/, sayHello)
	//启动服务,并标名端口
	ginServer.Run(":8082")
}

RESTful API

REST与技术无关,代表的始终软件架构风格,REST中文翻译为:表征状态转移或表现层状态转移

REST的含义就是客户端与web服务器之间进行交互的时候,使用HTTP协议中的4个请求方法表示不同的动作

  • GET用来获取资源->查
  • POST用来新建资源->增
  • PUT用来更新资源->改
  • DELETE用来删除资源->删

只要API程序遵循了REST风格,那就可以称其为RESTful API。目前在前后端分离的架构中,前后端都是通过RESTful API来进行交互

开发RESTful API的时候,我们通常石永Postman来作为客户端的测试

Go template

html/templage包时效内了数据驱动的模板,可以用于生成可防止代码注入的安全HTML内容,提供了和 text/template包向东的结构,Go语言中输出HTML场景都用 html/template

模板与渲染

模板可以理解为实现定义好的HTML文件,模板渲染的作用机制可以简单理解为文本替换操作

Go中的模板引擎

  1. 模板文件通常定义为.tmpl和.tpl,必须使用UTF8编码
  2. 模板文件中使用{{和}}包裹和表示需要传入的数据

Gin返回json

方法1,使用map

r.GET("/json", func(c *gin.Context) {
		// 	//方法1:使用map
		// 	data := map[string]interface{}{
		// 		"name":    "小王子",
		// 		"message": "hello,world!",
		// 		"age":     18,
		// 	}
		// 	c.JSON(http.StatusOK, data)
		// })
		//使用gin.H可以替代map,因为gin.H的本质也是map
		data := gin.H{"name": "小王子", "massage": "hello world!", "age": 18}
		c.JSON(http.StatusOK, data)
	})

方法2,使用结构体

//方法2:结构体,可以使用tag来对结构体字段做定制化操作
	type msg struct {
		Name    string //首字母如果不大写就无法导出
		Message string
		Age     int
	}
	r.GET("/another_json", func(c *gin.Context) {
		data := msg{
			"小王子",
			"Hello,golang!",
			18,
		}
		c.JSON(http.StatusOK, data) //本质上仍然是json的序列化
	})

gin获取querystring参数

使用query获取请求中携带的参数

r.GET("/web", func(c *gin.Context) {
		//获取浏览器那边发送请求携带的query String参数
		//name := c.Query("query") //通过Query获取请求中携带的querystring参数
		//name := c.DefaultQuery("query", "somebody")//如果取不到就用指定的默认值
		name, ok := c.GetQuery("query") //取不到第二个参数就返回false
		if !ok {
			name = "somebody"
		}
		c.JSON(200, gin.H{
			"name": name,
		})
	})

获取form参数

常用于登录页面

r.LoadHTMLFiles("./login.html")
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.html", nil)
	})
	//输入密码后按登录按键是属于POST请求,要用另外的POST函数来进行响应
	r.POST("/login", func(c *gin.Context) {
		// username := c.PostForm("uesrname")
		// password := c.PostForm("password")
		username := c.DefaultPostForm("username", "somebody")
		password := c.DefaultPostForm("password", "***")

		c.HTML(200, "index.html", gin.H{
			"Name":     username,
			"Password": password,
		})
	})

获取path参数/URL路径参数

	// 获取请求的path(URL)参数,返回的都是字符串类型
	// 注意URL的匹配不要冲突
	r.GET("/:name/:age", func(c *gin.Context) {
		//获取路径参数
		name := c.Param("name")//param就是得到(/:name)的值,以string类型返回
		age := c.Param("age")
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})

gin参数的绑定

var u UserInfo
		err := c.ShouldBind(&u) //可以把请求相关的值绑定给u
		//shouldbind可以根据请求的content-Type来自行选择绑定器
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
		} else {
			fmt.Printf("%#v\n", u)
			c.JSON(http.StatusOK, gin.H{
				"massage": "ok",
			})
		}

文件的上传

r.LoadHTMLFiles("./index.html")
	r.GET("/index", func(c *gin.Context) {
		c.HTML(200, "index.html", nil)
	})
	r.POST("/upload", func(c *gin.Context) {
		//从请求中读取文件
		f, err := c.FormFile("f1") //从请求中获取携带的参数
		//将读取到的文件保存到服务端本地
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
		} else {
			//将读取到的文件保存在本地
			// dst := fmt.Sprintf("./%s",f.Filename)
			dst := path.Join("./", f.Filename)
			c.SaveUploadedFile(f, dst)
			c.JSON(200, gin.H{
				"status": "OK",
			})
		}
	}) 

gin请求重定向

一个请求来到我的服务器之后将其转给其他服务器

r.GET("/index", func(c *gin.Context) {

		c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")

	})
	r.GET("/a", func(c *gin.Context) { //跳转到/b对应的路由处理函数
		c.Request.URL.Path = "/b"
		r.HandleContext(c)
	})
	r.GET("/b", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "b",
		})
	})

gin路由和路由组

r.Any("user", func(c *gin.Context) { //能处理所有常见的请求
		switch c.Request.Method {
		case "GET":
			c.JSON(http.StatusOK, gin.H{"method": "GET"})
		case "POST":
			c.JSON(http.StatusOK, gin.H{"method": "POST"})
		case "DELETE":
			c.JSON(http.StatusOK, gin.H{"method": "DELETE"})
		case "PUT":
			c.JSON(http.StatusOK, gin.H{"method": "PUT"})

		}

	})
	//没有路由的页面
	r.NoRoute(func(c *gin.Context) {
		c.JSON(http.StatusNotFound, gin.H{"msg": "liwenzhou.com"})
	})

	//路由组
	//把公用的前缀提取出来,创建一个路由组
	videoGroup := r.Group("/video")
	{
		videoGroup.GET("/index", func(c *gin.Context) { c.JSON(200, gin.H{"msg": "index"}) })
		videoGroup.GET("/swag", func(c *gin.Context) { c.JSON(200, gin.H{"msg": "swag"}) })

	}

了解cURL

用法:在终端用cURL URL就可以

有点像是命令行版的postman

  • 获取post请求
    • curl -XPOST URL 就可在终端直接获取URL返回的POST请求
    • 通常POST请求是要添加数据的,只要在末尾加入 -d 'JSON格式数据'即可
    • PUT,DELETE,GET以此类推
  • HTTP首部
    • 在 URL后,-d之前加入 -h即可添加制定首部
    • 在URL之前,-I即可查看首部
  • 下载文件
    • 小文件 在URL之前加入 -o 名称即可
    • 大文件 --limit-rate限定速度
    • 代理访问 curl --proxy 协议://用户名:密码@代理地址:端口 URL