一、基本路由
- gin 框架中采用的路由库是基于httprouter做的
- 地址为:https://github.com/julienschmidt/httprouter ```go package main
import ( “net/http”
"github.com/gin-gonic/gin"
)
func main() { r := gin.Default() r.GET(“/“, func(c *gin.Context) { c.String(http.StatusOK, “hello word”) }) r.POST(“/xxxpost”,getting) r.PUT(“/xxxput”) //监听端口默认为8080 r.Run(“:8000”) }
<a name="pbC2Q"></a>
# 二、Restful风格的API
- gin支持Restful风格的API
- 即Representational State Transfer的缩写。直接翻译的意思是”表现层状态转化”,是一种互联网应用程序的API设计理念:URL定位资源,用HTTP描述操作
1.获取文章 /blog/getXxx Get blog/Xxx<br />2.添加 /blog/addXxx POST blog/Xxx<br />3.修改 /blog/updateXxx PUT blog/Xxx<br />4.删除 /blog/delXxxx DELETE blog/Xxx
<a name="veuFC"></a>
## Restful风格
Restful是一种设计风格。对于我们Web开发人员来说。就是使用一个url地址表示一个唯一的资源。然后把原来的请求参数加入到请求资源地址中。然后原来请求的增,删,改,查操作。改为使用HTTP协议中请求方式GET、POST、PUT、DELETE表示。<br />把请求参数加入到请求的资源地址中<br />原来的增,删,改,查。使用HTTP请求方式,POST、DELETE、PUT、GET分别一一对应。<br />如何学习restful风格,这里需要明确两点:<br />1、就是把传统的请求参数加入到请求地址是什么样子?<br />传统的方式是:<br />比如:http://ip:port/工程名/资源名?请求参数<br />举例:[http://127.0.0.1:8080/springmvc/book?action=delete&id=1](http://127.0.0.1:8080/springmvc/book?action=delete&id=1)<br />restful风格是:<br />比如:http://ip:port/工程名/资源名/请求参数/请求参数<br />举例:[http://127.0.0.1:8080/springmvc/book/1](http://127.0.0.1:8080/springmvc/book/1)<br />请求的动作删除由请求方式delete决定
<a name="IuPn3"></a>
# 三、API参数
- 可以通过Context的Param方法来获取API参数
- localhost:8000/xxx/zhangsan
```go
package main
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/:name/*action", func(c *gin.Context) {
name := c.Param("name")
action := c.Param("action")
//截取/
action = strings.Trim(action, "/")
c.String(http.StatusOK, name+" is "+action)
})
//默认为监听8080端口
r.Run(":8000")
}
四、URL参数
- URL参数可以通过DefaultQuery()或Query()方法获取
- DefaultQuery()若参数不村则,返回默认值,Query()若不存在,返回空串
- API ? name=zs ```go package main
import ( “fmt” “net/http”
"github.com/gin-gonic/gin"
)
func main() { r := gin.Default() r.GET(“/user”, func(c *gin.Context) { //指定默认值 //http://localhost:8080/user 才会打印出来默认的值 name := c.DefaultQuery(“name”, “钟强”) c.String(http.StatusOK, fmt.Sprintf(“hello %s”, name)) }) r.Run() }
不加参数<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21940000/1655189492375-b24e12b6-c152-40cd-afa6-75fd9d09bf79.png#clientId=u7d086936-86f5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=131&id=u9816135e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=131&originWidth=316&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5879&status=done&style=none&taskId=u671d9514-cac4-4b20-82ac-266cb0eb11e&title=&width=316)<br />加传递参数<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21940000/1655189532835-09be6af1-6693-4121-b7ec-486c943ae626.png#clientId=u7d086936-86f5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=132&id=u8074be59&margin=%5Bobject%20Object%5D&name=image.png&originHeight=132&originWidth=388&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7018&status=done&style=none&taskId=uacc42cde-49ed-44e2-88f0-2e7407d7eed&title=&width=388)
<a name="fObEU"></a>
# 五、表单参数
- 表单传输为post请求,http常见的传输格式为四种:
- application/json
- application/x-www-form-urlencoded
- application/xml
- multipart/form-data
- 表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencoded或from-data格式的参数
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8080/form" method="post" action="application/x-www-form-urlencoded">
用户名:<input type="text" name="username" placeholder="请输入你的用户名"> <br>
密 码:<input type="password" name="userpassword" placeholder="请输入你的密码"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
package main
//
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.POST("/form", func(c *gin.Context) {
types := c.DefaultPostForm("type", "post")
username := c.PostForm("username")
password := c.PostForm("userpassword")
// c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))
c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))
})
r.Run()
}
六、上传单个文件
- multipart/form-data格式用于文件上传
- gin文件上传与原生的net/http方法类似,不同在于gin把原生的request封装到c.Request中
```go package main<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8000/upload" method="post" enctype="multipart/form-data">
上传文件:<input type="file" name="file" >
<input type="submit" value="提交">
</form>
</body>
</html>
import ( “github.com/gin-gonic/gin” )
func main() { r := gin.Default() //限制上传最大尺寸 r.MaxMultipartMemory = 8 << 20 r.POST(“/upload”, func(c *gin.Context) { file, err := c.FormFile(“file”) if err != nil { c.String(500, “上传图片出错”) } // c.JSON(200, gin.H{“message”: file.Header.Context}) c.SaveUploadedFile(file, file.Filename) c.String(http.StatusOK, file.Filename) }) r.Run() }
![image.png](https://cdn.nlark.com/yuque/0/2022/png/21940000/1655190082179-0e112648-1b28-402d-b40c-27820e7c8db6.png#clientId=u7d086936-86f5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=172&id=u93776faf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=172&originWidth=641&originalType=binary&ratio=1&rotation=0&showTitle=false&size=15200&status=done&style=none&taskId=u6eb80dec-56cb-4ef2-ac5c-08e786b3417&title=&width=641)
![image.png](https://cdn.nlark.com/yuque/0/2022/png/21940000/1655190069111-c270959b-7628-451c-8746-dfa65f4b740f.png#clientId=u7d086936-86f5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=169&id=ucf396fc9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=169&originWidth=447&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8096&status=done&style=none&taskId=u50327af2-1170-42b5-a35b-588ff68d778&title=&width=447)
<a name="gO6V3"></a>
## 上传特定文件
有的用户上传文件需要限制上传文件的类型以及上传文件的大小,但是gin框架暂时没有这些函数(也有可能是我没找到),因此基于原生的函数写法自己写了一个可以限制大小以及文件类型的上传函数
```go
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.POST("/upload", func(c *gin.Context) {
_, headers, err := c.Request.FormFile("file")
if err != nil {
log.Printf("Error when try to get file: %v", err)
}
//headers.Size 获取文件大小
if headers.Size > 1024*1024*2 {
fmt.Println("文件太大了")
return
}
//headers.Header.Get("Content-Type")获取上传文件的类型
if headers.Header.Get("Content-Type") != "image/png" {
fmt.Println("只允许上传png图片")
return
}
c.SaveUploadedFile(headers, "./video/"+headers.Filename)
c.String(http.StatusOK, headers.Filename)
})
r.Run(":8000")
}
七、上传多个文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8000/upload" method="post" enctype="multipart/form-data">
上传文件:<input type="file" name="files" multiple>
<input type="submit" value="提交">
</form>
</body>
</html>
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"fmt"
)
// gin的helloWorld
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// 限制表单上传大小 8MB,默认为32MB
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))
}
// 获取所有图片
files := form.File["files"]
// 遍历所有图片
for _, file := range files {
// 逐个存
if err := c.SaveUploadedFile(file, file.Filename); err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))
return
}
}
c.String(200, fmt.Sprintf("upload ok %d files", len(files)))
})
//默认端口号是8080
r.Run(":8000")
}
八、routes group
- routes group是为了管理一些相同的URL ```go package main
import ( “github.com/gin-gonic/gin” “fmt” )
// gin的helloWorld
func main() { // 1.创建路由 // 默认使用了2个中间件Logger(), Recovery() r := gin.Default() // 路由组1 ,处理GET请求 v1 := r.Group(“/v1”) // {} 是书写规范 { v1.GET(“/login”, login) v1.GET(“submit”, submit) } v2 := r.Group(“/v2”) { v2.POST(“/login”, login) v2.POST(“/submit”, submit) } r.Run(“:8000”) }
func login(c *gin.Context) { name := c.DefaultQuery(“name”, “jack”) c.String(200, fmt.Sprintf(“hello %s\n”, name)) }
func submit(c *gin.Context) { name := c.DefaultQuery(“name”, “lily”) c.String(200, fmt.Sprintf(“hello %s\n”, name)) }
![image.png](https://cdn.nlark.com/yuque/0/2022/png/21940000/1655190695854-1895986a-d20c-4eca-bed0-b158f63cae42.png#clientId=u7d086936-86f5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=126&id=ua7c967f5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=126&originWidth=427&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8155&status=done&style=none&taskId=u9fbcaa97-18d4-4157-b551-0e7d51f4f24&title=&width=427)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21940000/1655191117294-a2cbd26b-c212-4334-91f3-c2eca845b7b3.png#clientId=u7d086936-86f5-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=109&id=u0984bb80&margin=%5Bobject%20Object%5D&name=image.png&originHeight=109&originWidth=613&originalType=binary&ratio=1&rotation=0&showTitle=false&size=4582&status=done&style=none&taskId=u187f31e3-4737-45cd-9613-397310e4893&title=&width=613)
<a name="yNK3r"></a>
# 九、gin框架实现404页面
```go
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/user", func(c *gin.Context) {
//指定默认值
//http://localhost:8080/user 才会打印出来默认的值
name := c.DefaultQuery("name", "钟强")
c.String(http.StatusOK, fmt.Sprintf("hello %s", name))
})
r.NoRoute(func(c *gin.Context) {
c.String(http.StatusNotFound, "404 not found2222")
})
r.Run()
}
十、路由原理
- httprouter会将所有路由规则构造一颗前缀树
- 例如有 root and as at cn com