GoWeb开发的一大利器——gin框架的一些学习记录 第一部分。
一.响应
一.基本语句
1.Router参数
路由(Router)参数 用于处理请求。
其决定了当客户端(如浏览器或API调用者)发送请求到服务器时,服务器如何根据请求的URL和HTTP方法来执行相应的逻辑处理。
2.代码实现
用代码实现一个写有Hello,World!
字样的网页,并在localhost:8080
上运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import "github.com/gin-gonic/gin"
func main() {
//首先创建一个路由
router := gin.Default()
//绑定路由规则和路由函数,访问/index的路由,将有对应的函数去处理
router.GET("/index", func(context *gin.Context) {
context.String(200, "Hello,World!")
//状态码 http.StatusOK = 200 表示正常状态
})
//启动接听,gin会把web服务运行在localhost:8080上
_ = router.Run(":8080")
//或http.ListenAndServe(":8080",router) 基于http/net
}
其中,http/net
包自带的状态码包括:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
const (
StatusContinue = 100 // RFC 9110, 15.2.1
StatusSwitchingProtocols = 101 // RFC 9110, 15.2.2
StatusProcessing = 102 // RFC 2518, 10.1
StatusEarlyHints = 103 // RFC 8297
StatusOK = 200 // RFC 9110, 15.3.1
StatusCreated = 201 // RFC 9110, 15.3.2
StatusAccepted = 202 // RFC 9110, 15.3.3
StatusNonAuthoritativeInfo = 203 // RFC 9110, 15.3.4
StatusNoContent = 204 // RFC 9110, 15.3.5
StatusResetContent = 205 // RFC 9110, 15.3.6
StatusPartialContent = 206 // RFC 9110, 15.3.7
StatusMultiStatus = 207 // RFC 4918, 11.1
StatusAlreadyReported = 208 // RFC 5842, 7.1
StatusIMUsed = 226 // RFC 3229, 10.4.1
StatusMultipleChoices = 300 // RFC 9110, 15.4.1
StatusMovedPermanently = 301 // RFC 9110, 15.4.2
StatusFound = 302 // RFC 9110, 15.4.3
StatusSeeOther = 303 // RFC 9110, 15.4.4
StatusNotModified = 304 // RFC 9110, 15.4.5
StatusUseProxy = 305 // RFC 9110, 15.4.6
_ = 306 // RFC 9110, 15.4.7 (Unused)
StatusTemporaryRedirect = 307 // RFC 9110, 15.4.8
StatusPermanentRedirect = 308 // RFC 9110, 15.4.9
StatusBadRequest = 400 // RFC 9110, 15.5.1
StatusUnauthorized = 401 // RFC 9110, 15.5.2
StatusPaymentRequired = 402 // RFC 9110, 15.5.3
StatusForbidden = 403 // RFC 9110, 15.5.4
StatusNotFound = 404 // RFC 9110, 15.5.5
StatusMethodNotAllowed = 405 // RFC 9110, 15.5.6
StatusNotAcceptable = 406 // RFC 9110, 15.5.7
StatusProxyAuthRequired = 407 // RFC 9110, 15.5.8
StatusRequestTimeout = 408 // RFC 9110, 15.5.9
StatusConflict = 409 // RFC 9110, 15.5.10
StatusGone = 410 // RFC 9110, 15.5.11
StatusLengthRequired = 411 // RFC 9110, 15.5.12
StatusPreconditionFailed = 412 // RFC 9110, 15.5.13
StatusRequestEntityTooLarge = 413 // RFC 9110, 15.5.14
StatusRequestURITooLong = 414 // RFC 9110, 15.5.15
StatusUnsupportedMediaType = 415 // RFC 9110, 15.5.16
StatusRequestedRangeNotSatisfiable = 416 // RFC 9110, 15.5.17
StatusExpectationFailed = 417 // RFC 9110, 15.5.18
StatusTeapot = 418 // RFC 9110, 15.5.19 (Unused)
StatusMisdirectedRequest = 421 // RFC 9110, 15.5.20
StatusUnprocessableEntity = 422 // RFC 9110, 15.5.21
StatusLocked = 423 // RFC 4918, 11.3
StatusFailedDependency = 424 // RFC 4918, 11.4
StatusTooEarly = 425 // RFC 8470, 5.2.
StatusUpgradeRequired = 426 // RFC 9110, 15.5.22
StatusPreconditionRequired = 428 // RFC 6585, 3
StatusTooManyRequests = 429 // RFC 6585, 4
StatusRequestHeaderFieldsTooLarge = 431 // RFC 6585, 5
StatusUnavailableForLegalReasons = 451 // RFC 7725, 3
StatusInternalServerError = 500 // RFC 9110, 15.6.1
StatusNotImplemented = 501 // RFC 9110, 15.6.2
StatusBadGateway = 502 // RFC 9110, 15.6.3
StatusServiceUnavailable = 503 // RFC 9110, 15.6.4
StatusGatewayTimeout = 504 // RFC 9110, 15.6.5
StatusHTTPVersionNotSupported = 505 // RFC 9110, 15.6.6
StatusVariantAlsoNegotiates = 506 // RFC 2295, 8.1
StatusInsufficientStorage = 507 // RFC 4918, 11.5
StatusLoopDetected = 508 // RFC 5842, 7.2
StatusNotExtended = 510 // RFC 2774, 7
StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
)
3.响应
“响应”(Response)通常指的是服务器对客户端(如Web浏览器、移动应用或API调用者)发出的请求(Request)所做的回复。这个回复包含了服务器处理请求后生成的数据,以及关于这些数据的一些元信息。
二.数据序列化格式处理
1.json
a.结构体
下面用结构体类型来响应GET
指令,返回一段JSON
数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main
import (
"github.com/gin-gonic/gin"
)
func _json(c *gin.Context) {
type UserInfo struct {
Username string `json:"username"`
Age int `json:"age"`
Password string `json:"-"` //"-"表示忽略转换为json
} //定义一个结构体用于json转化
var Test UserInfo
Test = UserInfo{
Username: "Outer",
Age: 20,
Password: "123456",
} //为结构体赋值
c.JSON(200, Test) //将Test由结构体类型转化为JSON格式
}
func main() {
router := gin.Default()
router.GET("/json", _json)
err := router.Run(":8080")
if err != nil {
panic(err)
}
}
返回值:
1
2
3
4
{
"username": "Outer",
"age": 20
}
b.映射
通过构建map[string]string
来表示json
数据中的key
和value
关系
1
2
3
4
5
6
7
func _json(c *gin.Context) {
userMap := map[string]interface{}{
"username": "Outer",
"age": 18,
}
c.JSON(http.StatusOK, userMap)
}
返回值:
1
2
3
4
{
"age": 18,
"username": "Outer"
}
由于Go中的map是无序的,并且这个顺序对于用户来说是不透明的。
但对于JSON
来说,属性的顺序通常并不重要,因为JSON
是一个基于文本的数据交换格式,它定义的是数据的结构而不是数据的展示顺序。
c.输出gin.H{}
通过gin
自带的gin.H
来输出json值
在gin
的基层代码中是这要描述gin.H
的
1
2
// H is a shortcut for map[string]any
type H map[string]any
即gin.H
的本质是上述的映射,即map[string]interface{}
1
2
3
4
5
6
func _json(c *gin.Context) {
c.JSON(200, gin.H{
"username": "Outer",
"age": "18",
})
}
返回值:
1
2
3
4
{
"age": "18",
"username": "Outer"
}
2.xml
具体的函数可以依照json
的写法,此处以gin.H
输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/xml", func(c *gin.Context) {
c.XML(http.StatusOK, gin.H{
"username": "Outer",
"age": "18",
})
})
_ = router.Run(":8080")
}
返回值:
1
2
3
4
<map>
<username>Outer</username>
<age>18</age>
</map>
3.yaml
具体的函数可以依照json
的写法,此处以gin.H
输出
1
2
3
4
5
6
7
8
9
10
func main() {
router := gin.Default()
router.GET("/yaml", func(c *gin.Context) {
c.YAML(http.StatusOK, gin.H{
"username": "Outer",
"age": "18",
})
})
_ = router.Run(":8080")
}
返回值:
1
2
3
4
<map>
<username>Outer</username>
<age>18</age>
</map>
三.其他形式的响应
1.响应HTML
首先定义一个html
文件,相对路径为templates/index.html
(注:在go中,相对路径是相对于项目目录)
1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<header>HELLO
</header>
</body>
</html>
其中``````用于接受一个username
值并做出替换。
代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
// 响应html
func _html(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{"username": "Outer"}) //gin.H可以传参
}
func main() {
router := gin.Default()
//加载模版目录下所有html文件
router.LoadHTMLGlob("templates/*")
router.GET("/html", _html)
//在golang中,没有相对文件的路径,只有相对项目的路径
_ = router.Run(":8080")
}
返回值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<header>HELLO Outer
</header>
</body>
</html>
2.响应文件
现假定项目目录的pic
路径存有一张xdzn.png
的图片文件
现发出一个请求,要求返回文件xdzn.png
1
2
3
4
5
6
7
8
9
func main(){
router := gin.Default()
router.StaticFile("/pic", "./pic/xdzn.png")
//StaticFile用于访问路径对应的文件,即配置单个文件
router.StaticFS("/static", http.Dir("./pic"))
//StaticFS用于访问路径对应的所有文件,将整个文件夹的内容返回
//如可写localhost:8080/static/xdzn.png
_ = router.Run(":8080")
}
此时,可以通过两种URL路径获得这张png:
1
2
"localhost:8080/pic"
"localhost:8080/static/xdzn.png"
若访问"localhost:8080/static"
,则将返回html
数据:
1
2
3
<pre>
<a href="xdzn.png">xdzn.png</a>
</pre>
3.响应跳转
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import (
"github.com/gin-gonic/gin"
)
func _redirect(c *gin.Context) {
c.Redirect(301, "http://www.baidu.com")
}
func main() {
router := gin.Default()
router.GET("/baidu", _redirect)
_ = router.Run(":8080")
}
通过gin
包中的Redirect
方法来实现页面的跳转
上述代码可实现 当访问localhost:8080/baidu
时跳转至http://www.baidu.com
此处状态码301
和状态码302
的区别
- 301 Moved Permanently(永久重定向):这个状态码表示请求的URL已经被永久地移动到了由Location头部指定的新URL上。这意味着将来所有对该资源的引用都应该使用新的URI。搜索引擎在抓取到301状态码后,会将旧的URL替换为新的URL,并将旧URL的权重和排名转移到新URL上。
- 302 Found(临时重定向):这个状态码表示请求的URL暂时被移动到了由Location头部指定的新URL上。这通常发生在服务器暂时性地修改了资源的位置,但未来可能会恢复原始位置。搜索引擎在抓取到302状态码后,通常不会将旧的URL替换为新的URL,而是继续索引旧的URL,并在用户访问时将其重定向到新的URL。