快速进入gin
安装方式
$ go get -u github.com/gin-gonic/gin
引入gin
import "github.com/gin-gonic/gin"
gin的第一个小项目
package main
import (
"github.com/gin-gonic/gin"
)
func Hello(c *gin.Context) {
c.String(200, "hello,go")
}
func main() {
e := gin.Default()
e.GET("/hello", Hello)
e.Run()
}
复制代码
访问页面localhost:8080/hello 就可以看到hello,go
gin默认运行在8080端口,我们可以看出,gin其实是基于httprouter建立的,我们使用httprouter也可以还原上面的逻辑
package main
import (
"fmt"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
func Hello(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprintf(w, "hello,go")
}
func main() {
router := httprouter.New()
router.GET("/hello", Hello)
log.Fatal(http.ListenAndServe(":8080", router))
}
复制代码
但是我们明显可以发现,使用gin会优雅很多
使用gin简单写一个登陆
在gin中我们约定,将所有需要使用到的html文件都放到templates文件夹下
登陆页面 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
//方法名为post 因为我们需要用post方法调用提交功能,action为我们提交后需要跳转的位置
<form action="/welcome" method="post">
userName: <input type="text" class="text" name="userName"><br>
passWord: <input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
复制代码
登录成功后进入的界面 welcome.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
welcome {{.userName}}
</p>
</body>
</html>
复制代码
main.go
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func Login(c *gin.Context) {
c.HTML(http.StatusOK, "login.html", nil)
}
func DoWelcom(c *gin.Context) {
//*gin.Context是gin中一个非常关键的上下文流
// 为了拿到form内名为username输入框的内容
userName := c.PostForm("userName")
c.HTML(http.StatusOK, "welcome.html", gin.H{
//给welcone.html文件传递username
"userName": userName,
})
}
func main() {
e := gin.Default()
//获取html文件流
e.LoadHTMLGlob("templates/*")
e.GET("/login", Login)
e.POST("/welcome", DoWelcom)
e.Run()
}
复制代码
gin GET
GET其实就是进行穿参的一种方法,跟在路由后的params,下面的方法就类似于在路由路径后加上 ?username=""&password="" 123和111分别是默认数据
func testGet(c *gin.Context) {
s := c.DefaultQuery("username", "123")
password := c.DefaultQuery("password", "111")
c.String(200, "username:%s,password:%s", s, password)
}
复制代码
绑定查询参数
通过定义一个结构体来绑定表单内的参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<form action="/regiester" method="post">
userName: <input type="text" class="text" name="userName"><br>
passWord: <input type="password" name="password"><br>
爱好:
<input type="checkbox" name="hobby" value="swmming" id="">游泳
<input type="checkbox" name="hobby" value="run" id="">跑步
<br>
性别:
<input type="radio" name="gender" value="1" id="">男
<input type="radio" name="gender" value="2" id="">女
城市
<select name="city" id="">
<option value="beijing">北京</option>
<option value="shenzhen">深圳</option>
</select>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
复制代码
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
UserName string `form:"userName"`
Password string `form:"password"`
Hobby []string `form:"hobby"`
Gender string `form:"gender"`
City string `form:"city"`
}
func Regiester(c *gin.Context) {
var user User
c.ShouldBind(&user)
c.String(200, "USER:%s", user)
}
func main() {
e := gin.Default()
e.LoadHTMLGlob("templates/*")
e.GET("/login", Login)
e.POST("/regiester", Regiester)
e.Run()
}
复制代码
gin访问静态文件 例如bootstrap
- 首先去bootstrap官网下载bootstrap静态资源包,
- 在项目目录下创建一个assets的文件夹,用来存放静态资源,将bootstrap中下载的css和js包放到该文件夹下
- 创建一个templates文件夹用来存放html文件,创建一个html文件,然后再head标签中使用link导入css文件,script标签导入js文件,这里我们推荐使用bootstrap.min的包,意味小型,从而优化我们的页面加载速度
- 在go文件中使用gin引入html文件并挂载到8080端口
bootstrapExp.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="../assets/css/bootstrap.min.css">
<script src="../assets/js/bootstrap.min.js"></script>
</head>
<body>
<label for="customRange1" class="form-label">Example range</label>
<input type="range" class="form-range" id="customRange1">
</body>
</html>
复制代码
main.go
package main
import "github.com/gin-gonic/gin"
func assents(c *gin.Context) {
c.HTML(200, "bootstrapExp.html", nil)
}
func main() {
e := gin.Default()
e.LoadHTMLGlob("templates/*")
e.GET("/assents", assents)
e.Run()
}
复制代码
打开localhost:8080/assents就可以看到我们引入的bootstrap进度条组件
gin中间件
中间件就是在运行之后,构造之前中间这一段时间发生的方法,可以用来做数据处理,拦截等用途
当我们默认实例化gin时,使用到的gin.Default()方法,其实已经帮我们默认加载了两个中间件,我们看Default方法是怎么构成的
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
复制代码
Default方法创建gin实例时,默认加入logger和recovert中间件
当我们不想使用这两个中间件时,可以这样初始化gin
e:= gin.New()
复制代码
此时的e是没有任何中间件的
自己创建一个中间件
中间件其实就是一个方法,创建中间件就是创建一个方法,我们使用 Use()方法,把中间件方法作为参数传给Use()就是挂载了中间件
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func testMiddleWare(c *gin.Context) {
c.String(200, "hello,%s", "lyi")
}
func middleware1(c *gin.Context) {
fmt.Printf("你好我是中间件1")
}
func midellware2(c *gin.Context) {
fmt.Printf("你好我是中间件2")
}
func main() {
e := gin.Default()
e.Use(middleware1)
e.GET("/middleware", testMiddleWare)
e.Use(midellware2)
e.Run()
}
复制代码
我们可以看到middleware1和middleware2是在挂载前和挂载后的,在运行的时候,我们也就只能看到挂载前的中间件,也就是middleware1的运行结果
[GIN-debug] GET /middleware --> main.testMiddleWare (4 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
你好我是中间件1[GIN] 2022/06/23 - 14:59:05 | 200 | 66.292µs | ::1 | GET "/middleware"
复制代码
使用BasicAuth中间件
// 模拟一些私人数据
var secrets = gin.H{
"foo": gin.H{"email": "foo@bar.com", "phone": "123433"},
"austin": gin.H{"email": "austin@example.com", "phone": "666"},
"lena": gin.H{"email": "lena@guapa.com", "phone": "523443"},
}
func main() {
r := gin.Default()
// 路由组使用 gin.BasicAuth() 中间件
// gin.Accounts 是 map[string]string 的一种快捷方式
authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{
"foo": "bar",
"austin": "1234",
"lena": "hello2",
"manu": "4321",
}))
// /admin/secrets 端点
// 触发 "localhost:8080/admin/secrets
authorized.GET("/secrets", func(c *gin.Context) {
// 获取用户,它是由 BasicAuth 中间件设置的
user := c.MustGet(gin.AuthUserKey).(string)
if secret, ok := secrets[user]; ok {
c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret})
} else {
c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("})
}
})
// 监听并在 0.0.0.0:8080 上启动服务
r.Run(":8080")
}
复制代码
使用cookie
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
e := gin.Default()
e.GET("/cookie", func(ctx *gin.Context) {
s, err := ctx.Cookie("go_cookie")
if err != nil {
s = "no_cookie"
ctx.SetCookie("go_cookie", //cookie名称
s, //cookie实例
10, //cookie保存时间,单位是s
"/", //路径
"localhost", //域
false, //安全模式,如果开启,将只能通过https模式访问
true, //httpOnly
)
}
fmt.Printf("s: %v\n", s)
})
e.Run()
}
复制代码
打开浏览器我们就能在控制台中找到cookie数据