返回json
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/json", func(c *gin.Context) {
// 方法1:使用map
//data := map[string]interface{}{
// "name": "小王子",
// "message": "hello world!",
// "age": 18,
//}
data := gin.H{"name": "小王子", "message": "hello world!", "age": 18}
c.JSON(http.StatusOK, data)
})
// 方法2:结构体,灵活使用tag来对结构体字段做定制化操作
type msg struct {
Name string `json:"name"`
Message string
Age int
}
r.GET("/another_json", func(c *gin.Context) {
data := msg{
"小王子",
"Hello golang!",
18,
}
c.JSON(http.StatusOK, data)
})
r.Run(":9090")
}
获取querystring参数
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/web", func(c *gin.Context) {
// 获取浏览器那边发请求携带的 query string 参数
name := c.Query("query") // 通过Query获取请求中携带的querystring参数
age := c.Query("age")
//name := c.DefaultQuery("query", "somebody") // 取不到就用指定的默认值
//name, ok := c.GetQuery("query") // 取到返回(值, true),取不到返回("", false)
//if !ok {
// // 取不到
// name = "somebody"
//}
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
r.Run(":9090")
}
获取form参数
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="/login" method="post" novalidate autocomplete="off">
<div>
<label for="username">username:</label>
<input type="text" name="username" id="username">
</div>
<div>
<label for="password">password:</label>
<input type="password" name="password" id="password">
</div>
<div>
<input type="submit" value="登录">
</div>
</form>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>Hello, {{ .Name }}!</h1>
<p>你的密码是:{{ .Password }}</p>
</body>
</html>
main.go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
// 获取form表单提交的参数
func main() {
r := gin.Default()
r.LoadHTMLFiles("./login.html", "./index.html")
r.GET("/login", func(c *gin.Context) {
c.HTML(http.StatusOK, "login.html", nil)
})
// /login post
r.POST("/login", func(c *gin.Context) {
// 获取form表单提交的数据
//username := c.PostForm("username")
//password := c.PostForm("password")
//username := c.DefaultPostForm("username", "somebody")
//password := c.DefaultPostForm("password", "***")
username, ok := c.GetPostForm("username")
if !ok {
username = "sb"
}
password, ok := c.GetPostForm("password")
if !ok {
password = "***"
}
c.HTML(http.StatusOK, "index.html", gin.H{
"Name": username,
"Password": password,
})
})
r.Run(":9090")
}
获取URI路径参数
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
// 获取请求的path(uri)参数,返回的都是string类型
func main() {
r := gin.Default()
r.GET("/user/:name/:age", func(c *gin.Context) {
// 获取路径参数
name := c.Param("name")
age := c.Param("age")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
r.GET("/blog/:year/:month", func(c *gin.Context) {
year := c.Param("year")
month := c.Param("month")
c.JSON(http.StatusOK, gin.H{
"year": year,
"month": month,
})
})
r.Run(":9090")
}
参数绑定
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
type UserInfo struct {
Username string `form:"username" json:"user"`
Password string `form:"password" json:"pwd"`
}
func main() {
r := gin.Default()
r.GET("/user", func(c *gin.Context) {
//username := c.Query("username")
//password := c.Query("password")
//u := UserInfo{
// username: username,
// password: password,
//}
var u UserInfo // 声明一个UserInfo类型的变量u
err := c.ShouldBind(&u)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
} else {
fmt.Printf("%#v\n", u)
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
}
})
r.POST("/form", func(c *gin.Context) {
var u UserInfo // 声明一个UserInfo类型的变量u
err := c.ShouldBind(&u)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
} else {
fmt.Printf("%#v\n", u)
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
}
})
r.POST("/json", func(c *gin.Context) {
var u UserInfo // 声明一个UserInfo类型的变量u
err := c.ShouldBind(&u)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
} else {
fmt.Printf("%#v\n", u)
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
}
})
r.Run(":9090")
}
文件上传
file.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>file</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="f1">
<input type="submit" value="上传">
</form>
</body>
</html>
main.go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"path"
)
func main() {
r := gin.Default()
r.LoadHTMLFiles("./file.html")
r.GET("/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "file.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("./7/%s", f.Filename)
dst := path.Join("./7/", f.Filename)
c.SaveUploadedFile(f, dst)
c.JSON(http.StatusOK, gin.H{
"status": "OK",
})
}
})
r.Run(":8080")
}
请求重定向
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/index", func(c *gin.Context) {
// 跳转到sogo.com
c.Redirect(http.StatusMovedPermanently, "http://www.sogo.com")
})
r.GET("/a", func(c *gin.Context) {
// 跳转到 /b 对应的路由处理函数
c.Request.URL.Path = "/b" // 把请求的URI修改
r.HandleContext(c) // 继续后续的处理
})
r.GET("/b", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "b",
})
})
r.Run(":8080")
}
路由和路由组
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
// 访问/index的GET请求会走这一条处理逻辑
// 路由
//r.HEAD()
r.GET("/index", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"method": "GET",
})
})
r.POST("/index", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"method": "POST",
})
})
r.PUT("/index", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"method": "PUT",
})
})
r.DELETE("/index", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"method": "DELETE",
})
})
// Any:请求方法的大集合/大杂烩
r.Any("/user", func(c *gin.Context) {
switch c.Request.Method {
case http.MethodGet:
c.JSON(http.StatusOK, gin.H{"method": "GET"})
case http.MethodPost:
c.JSON(http.StatusOK, gin.H{"method": "POST"})
// ...
}
})
// NoRoute
r.NoRoute(func(c *gin.Context) {
c.JSON(http.StatusNotFound, gin.H{"msg": "liwenzhou.com"})
})
// 视频的首页和详情页
//r.GET("/video/index", func(c *gin.Context) {
// c.JSON(http.StatusOK, gin.H{"msg": "/video/index"})
//})
//r.GET("/video/a", func(c *gin.Context) {
// c.JSON(http.StatusOK, gin.H{"msg": "/video/a"})
//})
//r.GET("/video/b", func(c *gin.Context) {
// c.JSON(http.StatusOK, gin.H{"msg": "/video/b"})
//})
// 路由组的组
// 把公用的前缀提取出来,创建一个路由组
videoGroup := r.Group("/video")
{
videoGroup.GET("/index", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"msg": "/video/index"})
})
videoGroup.GET("/a", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"msg": "/video/a"})
})
videoGroup.GET("/b", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"msg": "/video/b"})
})
}
r.Run(":9090")
}
中间件
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func indexHandler(c *gin.Context) {
fmt.Println("index")
name, ok := c.Get("name") // 从上下文中取值(跨中间件存取值)
if !ok {
name = "匿名用户"
}
c.JSON(http.StatusOK, gin.H{
"msg": name,
})
}
// 定义一个中间件m1:统计请求处理函数的耗时
func m1(c *gin.Context) {
fmt.Println("m1 in...")
// 计时
start := time.Now()
c.Next() // 调用后续的处理函数
cost := time.Since(start)
fmt.Printf("cost:%v\n", cost)
fmt.Println("m1 out...")
}
func m2(c *gin.Context) {
fmt.Println("m2 in...")
c.Set("name", "q1mi") // 在上下文c中设置值
//c.Abort() // 阻止调用后续的处理函数
fmt.Println("m2 out...")
}
func authMiddleware(doCheck bool) gin.HandlerFunc {
// 连接数据库
// 或做一些其他准备工作
return func(c *gin.Context) {
if doCheck {
// 存放具体的逻辑
// 是否登录的判断
// if 是登录用户
// c.Next()
// else
// c.Abort()
} else {
c.Next()
}
}
}
func main() {
r := gin.Default()
r.Use(m1, m2, authMiddleware(true)) // 全局注册中间件函数
r.GET("/index", indexHandler)
r.GET("/shop", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "shop",
})
})
r.GET("/user", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "user",
})
})
// 路由组注册中间件方法1:
xxGroup := r.Group("/xx", authMiddleware(true))
{
xxGroup.GET("/index", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "xxGroup",
})
})
}
// 路由组注册中间件方法2:
xx2Group := r.Group("/xx2")
xx2Group.Use(authMiddleware(true))
{
xx2Group.GET("/index", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "xx2Group",
})
})
}
r.Run()
}
后记
篇幅内容有限,了解更多:https://www.liwenzhou.com/
参考
[1] B站:BV1gJ411p7xC