安裝 gin 框架
go get -u github.com/gin-gonic/gin
HelloWorld
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
// 創(chuàng)建一個(gè)默認(rèn)路由
router := gin.Default()
// 綁定路由規(guī)則和函數(shù)
router.GET("/index", func(context *gin.Context) {
context.String(200, "HelloWorld !")
})
// 啟動(dòng)服務(wù)
router.Run(":8080")
// 第二種啟動(dòng)服務(wù)的方式
//http.ListenAndServe(":8080", router)
}
gin數(shù)據(jù)響應(yīng)
響應(yīng) string
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/str", respStr)
router.Run(":80")
}
func respStr(c *gin.Context) {
c.String(http.StatusOK, "hello world!")
}
響應(yīng) json
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/str", respStr)
router.Run(":80")
}
func respJson(c *gin.Context) {
//1. json響應(yīng)結(jié)構(gòu)體
type User struct {
Username string `json:"username"`
Age int `json:"age"`
Password string `json:"-"` // "-"表示序列化的時(shí)候跳過(guò)該字段
}
user := User{
Username: "Hale",
Age: 20,
Password: "qwe23",
}
c.JSON(http.StatusOK, user)
//2. json 響應(yīng) map
userMap := map[string]string{
"username": "TT",
"age": "23",
}
c.JSON(http.StatusOK, userMap)
//3. 直接響應(yīng) json
c.JSON(http.StatusOK, gin.H{"username": "TT", "age": 14})
}
響應(yīng) xml
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/xml", respXml)
router.Run(":80")
}
func respXml(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"username": "TT", "age": 14})
}
重定向
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/redirect", respRedirect)
router.Run(":80")
}
func respRedirect(c *gin.Context) {
c.Redirect(http.StatusFound, "https://baidu.com")
}
gin 請(qǐng)求參數(shù)
獲取查詢參數(shù)
package main
import (
"github.com/gin-gonic/gin"
)
// 獲取查詢傳參
func _query(c *gin.Context) {
user := c.Query("user")
//user, ok := c.GetQuery("user")
c.QueryArray("user") // 多個(gè)相同查詢參數(shù)的切片
c.String(200, user)
}
func main() {
router := gin.Default()
router.GET("/query", _query)
router.Run(":80")
}
// http://127.0.0.1
獲取動(dòng)態(tài)參數(shù)
package main
import (
"github.com/gin-gonic/gin"
)
// 獲取查詢傳參
func _param(c *gin.Context) {
param := c.Param("user_id")
c.String(200, param)
}
func main() {
router := gin.Default()
router.GET("/param/:user_id/", _param)
router.GET("/param/:user_id/:age/", _param)
router.Run(":80")
}
// http://127.0.0.1/param/xxx
表單參數(shù) PostForm
package main
import (
"github.com/gin-gonic/gin"
)
// 獲取查詢傳參
func _form(c *gin.Context) {
param := c.PostForm("name")
params := c.PostFormArray("name")
form := c.DefaultPostForm("user", "Jelo") // 如果沒(méi)傳就指定默認(rèn)值
c.String(200, param)
}
func main() {
router := gin.Default()
router.POST("/form", _form)
router.Run(":80")
}
原始參數(shù) GetRawData
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
)
// 解析 json 數(shù)據(jù)的封裝
func bindJson(c *gin.Context, obj any) (err error) {
body, _ := c.GetRawData()
ContentType := c.GetHeader("Content-Type")
switch ContentType {
case "application/json":
err = json.Unmarshal(body, &obj)
if err != nil {
return err
}
}
return nil
}
// 獲取原始參數(shù)
func _raw(c *gin.Context) {
type User struct {
Name string `json:"name"`
Age string `json:"age"`
}
var user User
err := bindJson(c, &user)
if err != nil {
fmt.Print(err)
}
c.JSON(200, user)
}
func main() {
router := gin.Default()
router.POST("/raw", _raw)
router.Run(":80")
}
四大請(qǐng)求方式
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
)
type Article struct {
Title string `json:"title"`
Content string `json:"content"`
}
type Response struct {
Code int `json:"code"`
Data any `json:"data"`
Msg string `json:"msg"`
}
func bindToJson(c *gin.Context, obj any) (err error) {
body, _ := c.GetRawData()
ContentType := c.GetHeader("Content-Type")
switch ContentType {
case "application/json":
err = json.Unmarshal(body, &obj)
if err != nil {
return err
}
}
return nil
}
func getList(c *gin.Context) {
data := []Article{
{Title: "Test1", Content: "xxxxxx"},
{Title: "Test2", Content: "xxxxxx"},
}
c.JSON(200, Response{0, data, "succ"})
}
func getDetail(c *gin.Context) {
// 從 param 中獲取 id
c.Param("id")
article := Article{
Title: "Test1", Content: "xxxxxx",
}
c.JSON(200, Response{0, article, "succ"})
}
func create(c *gin.Context) {
// 接收前端傳遞來(lái)的數(shù)據(jù)
var article Article
err := bindToJson(c, &article)
if err != nil {
fmt.Print(err)
}
c.JSON(200, Response{0, article, "succ"})
}
func update(c *gin.Context) {
// 從 param 中獲取 id
c.Param("id")
var article Article
err := bindToJson(c, &article)
if err != nil {
fmt.Print(err)
}
c.JSON(200, Response{0, article, "succ"})
}
func delete(c *gin.Context) {
c.Param("id")
// 庫(kù)里面刪除
c.JSON(200, Response{0, map[string]string{}, "succ"})
}
func main() {
router := gin.Default()
router.GET("/articles", getList)
router.GET("/articles/:id/", getDetail)
router.POST("/articles", create)
router.PUT("/articles/:id/", update)
router.DELETE("/articles/:id/", delete)
router.Run(":80")
}
請(qǐng)求頭相關(guān)
請(qǐng)求頭參數(shù)獲取
package main
import (
"github.com/gin-gonic/gin"
"strings"
)
func main() {
engine := gin.Default()
engine.GET("/", func(c *gin.Context) {
// 首字母不區(qū)分大小寫
c.GetHeader("User-Agent")
c.JSON(200, gin.H{"msg": "succ"})
// 自定義請(qǐng)求頭可以按照如下獲取
c.Request.Header.Get("token")
})
// demo1 反爬蟲
engine.GET("/index", func(c *gin.Context) {
userAgent := c.GetHeader("User-Agent")
// 正則或者字符串包含匹配
if strings.Contains(userAgent, "python") {
//todo
}
})
engine.Run(":80")
}
響應(yīng)頭相關(guān)
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
engine := gin.Default()
engine.GET("/", func(c *gin.Context) {
// 設(shè)置響應(yīng)頭
c.Header("Token", "asfwx13ssc23")
c.JSON(200, gin.H{"msg": "succ"})
})
engine.Run(":80")
}
bind 綁定參數(shù)
gin 中的 bind 可以很方便的將前端穿都來(lái)的數(shù)據(jù)與結(jié)構(gòu)體進(jìn)行參數(shù)綁定
ShouldBindJSON
綁定請(qǐng)求 body 里面的參數(shù)到結(jié)構(gòu)體
package main
import (
"github.com/gin-gonic/gin"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Sex string `json:"sex"`
}
func main() {
router := gin.Default()
router.POST("/", func(c *gin.Context) {
var userInfo User
// 這里的 bind 會(huì)自帶參數(shù)校驗(yàn)功能
err := c.ShouldBindJSON(&userInfo)
if err != nil {
c.JSON(200, "userInfo failed")
return
}
c.JSON(200, userInfo)
})
router.Run(":80")
}
ShouldBindQuery
綁定請(qǐng)求查詢參數(shù)(params)的參數(shù)到結(jié)構(gòu)體
tag 對(duì)應(yīng) form
package main
import (
"github.com/gin-gonic/gin"
)
type User struct {
Name string `json:"name" form:"name"`
Age int `json:"age" form:"age"`
Sex string `json:"sex" form:"sex"`
}
func main() {
router := gin.Default()
router.POST("/", func(c *gin.Context) {
var userInfo User
// 這里的 bind 會(huì)自帶參數(shù)校驗(yàn)功能
err := c.ShouldBindQuery(&userInfo)
if err != nil {
c.JSON(200, "userInfo failed")
return
}
c.JSON(200, userInfo)
})
router.Run(":80")
}
ShouldBindUri
綁定 url 中的參數(shù)到結(jié)構(gòu)體瘸右,用法參考ShouldBindQuery
ShouldBind
會(huì)根據(jù)請(qǐng)求頭中的 content-type 去自動(dòng)綁定
form-data 的參數(shù)也用這個(gè)咧擂,tag 用 form
func main() {
router := gin.Default()
router.POST("/form", func(c *gin.Context) {
var userInfo User
// 這里的 bind 會(huì)自帶參數(shù)校驗(yàn)功能
err := c.ShouldBind(&userInfo)
if err != nil {
c.JSON(200, "userInfo failed")
return
}
c.JSON(200, userInfo)
})
router.Run(":80")
}
bind常用驗(yàn)證器
package main
import (
"github.com/gin-gonic/gin"
)
type User struct {
Name string `json:"name" binding:"required"`
Age int `json:"age" binding:"lt=30,gt=18"`
Password string `json:"password"`
RePassword string `json:"re_password" binding:"eqfield=Password"`
Hobby []string `json:"hobby" binding:"required,dive,startswith=xx"`
}
func main() {
router := gin.Default()
router.POST("/", func(c *gin.Context) {
var user User
err := c.ShouldBindJSON(&user)
if err != nil {
c.JSON(200, gin.H{"msg": err.Error()})
} else {
c.JSON(200, gin.H{"msg": user})
}
})
router.Run(":80")
}
/*
required: 必須字段
min,max:最大最小驗(yàn)證
len 長(zhǎng)度驗(yàn)證囤耳,例如 bingding:"len=6"
eq,ne,gt,gte,lt,lte
eqfield 等于其它字段的值,例如 RePassword string `binding:"eqfield=Password"`
nefield 不等于其它字段的值
- 忽略猴哥字段,例如:binding:"-"
*/
其它內(nèi)置驗(yàn)證器
/*
枚舉
oneof=red green
字符串
contains=harry
excludes // 不包含
startswith
endswith
數(shù)組
dive 例如 Hobby []string `json:"hobby" binding:"required,dive,startswith=xx"`
網(wǎng)絡(luò)驗(yàn)證
ip次乓,ipv4,ipv6雳窟,uri尊浪,url
*/
自定義錯(cuò)誤信息
package main
import (
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"reflect"
)
type User struct {
Name string `json:"name" binding:"required" msg:"用戶名必須"`
Age int `json:"age" binding:"lt=30,gt=18"`
Sex string `json:"sex" binding:"oneof=man women"`
Hobby []string `json:"hobby" binding:"required,dive,startswith=xx"`
}
func GetValidMsg(obj any, err error) string {
getObj := reflect.TypeOf(obj)
if err != nil {
// 將 err 接口斷言為具體類型
if errs, ok := err.(validator.ValidationErrors); ok {
for _, e := range errs {
// 根據(jù)報(bào)錯(cuò)字段名獲取結(jié)構(gòu)體的具體字段
if f, exists := getObj.Elem().FieldByName(e.Field()); exists {
msg := f.Tag.Get("msg")
return msg
}
}
}
}
return err.Error()
}
func main() {
router := gin.Default()
router.POST("/", func(c *gin.Context) {
var user User
err := c.ShouldBindJSON(&user)
if err != nil {
c.JSON(200, gin.H{"msg": GetValidMsg(&user, err)})
return
}
c.JSON(200, gin.H{"data": user})
})
router.Run(":80")
}
自定義驗(yàn)證器
package main
import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `json:"name" binding:"required,sign"`
Age int `json:"age" binding:"lt=30,gt=18"`
}
func main() {
router := gin.Default()
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("sign", signValid)
}
router.POST("/", func(c *gin.Context) {
var user User
err := c.ShouldBindJSON(&user)
if err != nil {
c.JSON(200, gin.H{"msg": err.Error()})
return
}
c.JSON(200, gin.H{"data": user})
})
router.Run(":80")
}
func signValid(fl validator.FieldLevel) bool {
var nameList = []string{"asa", "sdfa", "csd"}
for _, nameStr := range nameList {
name := fl.Field().Interface().(string)
if name == nameStr {
return false
}
}
return true
}