[ go 与 golang | 青训营笔记]
这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天, 在学习了go的相关基础知识以后,可以说是初步的了解了go,接下来,我们将步入全新的环节,今天我们学习go的一个常用web框架gin
1. gin之hello world
Gin在GitHub上已经有47k的star,它和Golang的语法一样简洁明了,使得初学者得以迅速入门。
安装
命令行输入
go get -u github.com/gin-gonic/gin
hello world
使用gin编写一个接口也是非常简单
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello World")
})
router.Run(":8000")
}
router:=gin.Default():这是默认的服务器。使用gin的Default方法创建一个路由Handler;- 然后通过Http方法绑定路由规则和路由函数。不同于
net/http库的路由函数,gin进行了封装,把request和response都封装到了gin.Context的上下文环境中。 - 最后启动路由的Run方法监听端口。还可以用
http.ListenAndServe(":8080", router),或者自定义Http服务器配置。
两种启动方式
// 启动方式一
router.Run(":8000")
// 启动方式二
http.ListenAndServe(":8000", router)
修改ip为内网ip
router.Run("0.0.0.0:8000")
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func Index(context *gin.Context) {
context.String(200, "Hello zhaoran!")
}
func main() {
// 创建一个默认的路由
router := gin.Default()
// 绑定路由规则和路由函数,访问/index的路由,将由对应的函数去处理
router.GET("/index", Index)
// 启动监听,gin会把web服务运行在本机的0.0.0.0:8080端口上
router.Run("0.0.0.0:8080")
// 用原生http服务的方式, router.Run本质就是http.ListenAndServe的进一步封装
http.ListenAndServe(":8080", router)
}
2. 响应码概述
状态码
200 表示正常响应 http.StatusOK
响应
返回字符串
router.GET("/index", func(c *gin.Context) {
c.String(http.StatusOK, "hello world")
})
返回json
router.GET("/json", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
})
// 结构体转json
router.GET("/moreJSON", func(c *gin.Context) {
// You also can use a struct
type Msg struct {
Name string `json:"user"`
Message string
Number int
}
msg := Msg{"fengfeng", "hey", 21}
// 注意 msg.Name 变成了 "user" 字段
// 以下方式都会输出 : {"user": "hanru", "Message": "hey", "Number": 123}
c.JSON(http.StatusOK, msg)
})
返回xml
router.GET("/xml", func(c *gin.Context) {
c.XML(http.StatusOK, gin.H{"user": "hanru", "message": "hey", "status": http.StatusOK})
})
返回yaml
router.GET("/yaml", func(c *gin.Context) {
c.YAML(http.StatusOK, gin.H{"user": "hanru", "message": "hey", "status": http.StatusOK})
})
返回html
先要使用 LoadHTMLGlob()或者LoadHTMLFiles()方法来加载模板文件
//加载模板
router.LoadHTMLGlob("gin框架/templates/*")
//router.LoadHTMLFiles("templates/index.html", "templates/index2.html")
//定义路由
router.GET("/html", func(c *gin.Context) {
//根据完整文件名渲染模板,并传递参数
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "hello world",
})
})
在模板中使用这个title,需要使用{{ .title }}
不同文件夹下模板名字可以相同,此时需要 LoadHTMLGlob() 加载两层模板路径。
router.LoadHTMLGlob("templates/**/*")
router.GET("/posts/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "posts/index.html", gin.H{
"title": "Posts",
})
c.HTML(http.StatusOK, "users/index.html", gin.H{
"title": "Users",
})
})
文件响应
// 在golang总,没有相对文件的路径,它只有相对项目的路径
// 网页请求这个静态目录的前缀, 第二个参数是一个目录,注意,前缀不要重复
router.StaticFS("/static", http.Dir("static/static"))
// 配置单个文件, 网页请求的路由,文件的路径
router.StaticFile("/titian.png", "static/titian.png")
重定向
router.GET("/redirect", func(c *gin.Context) {
//支持内部和外部的重定向
c.Redirect(http.StatusMovedPermanently, "https://www.baidu.com/")
})
301 Moved Permanently
被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。
302 Found
请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
3. 请求方式
RESTful API介绍
REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”。
简单来说,REST的含义就是客户端与Web服务器之间进行交互的时候,使用HTTP协议中的4个请求方法代表不同的动作。
GET用来获取资源
POST用来新建资源
PUT用来更新资源
DELETE用来删除资源。
请求参数
查询参数 Query
func _query(c *gin.Context) {
fmt.Println(c.Query("user"))
fmt.Println(c.GetQuery("user"))
fmt.Println(c.QueryArray("user")) // 拿到多个相同的查询参数
fmt.Println(c.DefaultQuery("addr", "内蒙古"))
}
动态参数 Param
func _param(c *gin.Context) {
fmt.Println(c.Param("user_id"))
fmt.Println(c.Param("book_id"))
}
router.GET("/param/:user_id/", _param)
router.GET("/param/:user_id/:book_id", _param)
// ?param/12
// ?param/12/123
表单 PostForm
可以接收 multipart/form-data; 和 application/x-www-form-urlencoded
func _form(c *gin.Context) {
fmt.Println(c.PostForm("name"))
fmt.Println(c.PostFormArray("name"))
fmt.Println(c.DefaultPostForm("addr", "内蒙古")) // 如果用户没传,就使用默认值
forms, err := c.MultipartForm() // 接收所有的form参数,包括文件
fmt.Println(forms, err)
}