0
点赞
收藏
分享

微信扫一扫

第22章 go的web框架-gin

目录

  • ​​1 gin的helloworld体验​​
  • ​​2 使用New和Default初始化路由器的区别​​
  • ​​3 gin的路由分组​​
  • ​​4 获取url中的变量​​
  • ​​5 获取get和post表单信息​​
  • ​​6 gin返回protobuf​​
  • ​​7 登录的表单验证​​
  • ​​8 注册表单的验证​​
  • ​​9 表单验证错误翻译成中文​​
  • ​​10 表单中文翻译的json格式化细节​​
  • ​​11 自定义gin中间件​​
  • ​​12 通过abort终止中间件后续逻辑的执行​​
  • ​​13 gin的中间件原理源码分析​​
  • ​​14 gin返回html​​
  • ​​15 加载多个html文件​​
  • ​​16 static静态文件的处理​​
  • ​​17 gin的优雅退出​​

1 gin的helloworld体验

2 使用New和Default初始化路由器的区别

new 没有错误捕捉

3 gin的路由分组

4 获取url中的变量

5 获取get和post表单信息

查看代码

6 gin返回protobuf

第22章 go的web框架-gin_json

z_ch22/gin_start/ch06/main.go

查看代码

package main

import (
"ch06/proto"
"github.com/gin-gonic/gin"
"net/http"
)

func main() {
router := gin.Default()

router.GET("/moreJSON", moreJSON)
router.GET("/someProtoBuf", returnProto)

router.Run(":8083")
}

func returnProto(c *gin.Context) {
course := []string{"python", "go", "微服务"}
user := &proto.Teacher{
Name: "lele",
Course: course,
}
c.ProtoBuf(http.StatusOK, user)
}

func moreJSON(c *gin.Context) {
var msg struct {
Name string `json:"user"`
Message string
Number int
}
msg.Name = "bobby"
msg.Message = "这是一个测试json"
msg.Number = 20

c.JSON(http.StatusOK, msg)
}

z_ch22/gin_start/ch06/proto/user.proto

查看代码

syntax = "proto3";
option go_package = "./;proto"; // 要指明路径为当前的相对路径,不然会报错
message Teacher{
string name = 1;
repeated string course = 2;
}

然后在文件目录同级的命令行执行下面的命令:

​protoc -I . user.proto --go_out=plugins=grpc:.​​ 会生成 user.pb.go

拷贝相同的user.proto 文件到python的目录下面,

生成pyhton的proto文件

先安确保安装以下包

pip install grpcio
pip install grpcio-tools

然后在同级目录的命令行执行

​python -m grpc_tools.protoc -I=./ --python_out=. --grpc_python_out=. ./user.proto​

会生成 ​​user_pb2.py 、user_pb2_grpc.py​​ 两个文件

编写python请求

查看代码

import requests

import user_pb2

user = user_pb2.Teacher()

rsp = requests.get("http://127.0.0.1:8083/someProtoBuf")

user.ParseFromString(rsp.content)
print(user.name, user.course)

结果执行结果: ​​lele ['python', 'go', '微服务']​

7 登录的表单验证

​https://pkg.go.dev/github.com/go-playground/validator/v10#section-readme​

8 注册表单的验证

9 表单验证错误翻译成中文

10 表单中文翻译的json格式化细节

查看代码

package main

import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
"net/http"
"reflect"
"strings"
)

var trans ut.Translator

type LoginForm struct {
User string `json:"user" binding:"required,min=3,max=10"`
Password string `json:"password" binding:"required"`
}

type SignUpForm struct {
Age uint8 `json:"age" binding:"gte=1,lte=130"`
Name string `json:"name" binding:"required,min=3"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required"`
RePassword string `json:"re_password" binding:"required,eqfield=Password"` //跨字段
}

func InitTrans(locale string) (err error) {
//修改gin框架中的validator引擎属性, 实现定制
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
//注册一个获取json的tag的自定义方法
v.RegisterTagNameFunc(func(field reflect.StructField) string {
fmt.Println("---", field.Tag.Get("json"))
name := strings.SplitN(field.Tag.Get("json"), ",", 2)[0]
if name == "-" { // 不处理
return ""
}
return name
})
zhT := zh.New() //中文翻译器
enT := en.New() //英文翻译器
//第一个参数是备用的语言环境,后面的参数是应该支持的语言环境
uni := ut.New(enT, zhT, enT)

// 获取全局翻译
trans, ok = uni.GetTranslator(locale)
if !ok {
return fmt.Errorf("uni.GetTranslator(%s)", locale)
}

switch locale {
case "en":
en_translations.RegisterDefaultTranslations(v, trans)
case "zh":
zh_translations.RegisterDefaultTranslations(v, trans)
default:
en_translations.RegisterDefaultTranslations(v, trans)
}
return
}
return
}

func removeTopStruct(fileds map[string]string) map[string]string {
fmt.Println("1111", fileds)
rsp := map[string]string{}
for filed, err := range fileds {
//fmt.Println(filed, err)
// 截取LoginForm.user '.' 后的字段
rsp[filed[strings.Index(filed, ".")+1:]] = err
}
fmt.Println("222222", rsp)
return rsp
}

func main() {
//代码侵入性很强 中间件
if err := InitTrans("zh"); err != nil {
fmt.Println("初始化翻译器错误")
return
}

router := gin.Default()
router.POST("/loginJSON", func(c *gin.Context) {
var loginForm LoginForm
if err := c.ShouldBind(&loginForm); err != nil {
fmt.Println("LoginForm err", err)
errs, ok := err.(validator.ValidationErrors)

fmt.Println("-----", errs, ok)
if !ok { // 如果没有捕捉到
c.JSON(http.StatusOK, gin.H{
"msg": err.Error(),
})
}

c.JSON(http.StatusBadRequest, gin.H{

"error": removeTopStruct(errs.Translate(trans)),
})
return

}

c.JSON(http.StatusOK, gin.H{
"msg": "登录成功",
})

})

router.POST("/signup", func(c *gin.Context) {
var signUpForm SignUpForm
if err := c.ShouldBind(&signUpForm); err != nil {
fmt.Println(err.Error())
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"msg": "注册成功",
})
})

_ = router.Run(":8083")
}

11 自定义gin中间件

12 通过abort终止中间件后续逻辑的执行

13 gin的中间件原理源码分析

注册的中间件添加到了handler 的尾部

第22章 go的web框架-gin_json_02

第22章 go的web框架-gin_json_03

第22章 go的web框架-gin_github_04

第22章 go的web框架-gin_中间件_05

改成 abort index

第22章 go的web框架-gin_中间件_06

移到最大的数

第22章 go的web框架-gin_中间件_07

查看代码

package main

import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)

func MyLogger() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
c.Set("example", "123456")
//让原本改执行的逻辑继续执行
c.Next()

end := time.Since(t)
fmt.Printf("耗时:%V\n", end)
status := c.Writer.Status()
fmt.Println("状态", status)
}
}

func TokenRequired() gin.HandlerFunc {
return func(c *gin.Context) {
var token string
fmt.Println("headers", c.Request.Header)
for k, v := range c.Request.Header {

if k == "X-Token" {
token = v[0]
} else {
fmt.Println(k, v)
}
}

if token != "lele" {
c.JSON(http.StatusUnauthorized, gin.H{
"msg": "未登录",
})
//挑战 为什么连return都阻止不了后续逻辑的执行
c.Abort()
}
c.Next()
}
}

func main() {
router := gin.Default()
//使用logger和recovery中间件 全局所有
router.Use(TokenRequired())

router.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})

router.Run(":8083")
}

请求测试

查看代码

import requests

rsp = requests.get("http://127.0.0.1:8083/ping", headers={
"x-token":"lele"
})
print(rsp.text)

14 gin返回html

15 加载多个html文件

16 static静态文件的处理

17 gin的优雅退出

查看代码



举报

相关推荐

Go Web 开发【Gin 框架快速开发】

1.go web之gin框架

Go语言Web框架Gin常见用法

Go gin框架

Go的Gin框架学习

Go 之 Gin 框架

go-gin框架

0 条评论