这是我参与「第五届青训营 」笔记创作活动的第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中的模板引擎
- 模板文件通常定义为.tmpl和.tpl,必须使用UTF8编码
- 模板文件中使用{{和}}包裹和表示需要传入的数据
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后,-d之前加入
- 下载文件
- 小文件 在URL之前加入
-o 名称即可 - 大文件
--limit-rate限定速度 - 代理访问
curl --proxy 协议://用户名:密码@代理地址:端口 URL
- 小文件 在URL之前加入