测试、Gin、编码规范 | 青训营笔记

414 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

测试

单元测试

文件定义规则

1、所有测试文件以 _test.go 结尾

2、方法名定义,func TestXxx(*testing.T)

3、初始化逻辑放到TestMain中,模板如下

func TestMain(m *testing.M) {
   // 测试前: 数据装载、配置初始化等前置工作
   code := m.Run()
   // 测试后:释放资源等收尾工作
   os.Exit(code)
}

覆盖率

代码覆盖率是检验一个代码单元测试的标准。

项目实战

分词结构

常用的三层结构模型

image.png

Gin简单使用

文档 | Gin Web Framework (gin-gonic.com)

RESTful风格

RESTful API 的规范建议我们使用特定的HTTP方法来对服务器上的资源进行操作。如:

  1. GET,表示读取服务器上的资源
  2. POST,表示在服务器上创建资源
  3. PUT,表示更新或者替换服务器上的资源
  4. DELETE,表示删除服务器上的资源
  5. PATCH,表示更新、修改资源的一部分

分组路由

package main

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

func main() {
   r := gin.Default()
   // 分组路由
   // 用户
   user := r.Group("/user")
   {
      user.GET("/:id", func(context *gin.Context) {
         msg := context.Param("id")
         context.JSON(200, gin.H{"msg": msg})
      })
      user.GET("/find", func(context *gin.Context) {
         context.JSON(200, "find")
      })
   }
   // 订单
   order := r.Group("/order")
   {
      order.GET("/:id", func(context *gin.Context) {
         msg := context.Param("id")
         context.JSON(200, gin.H{"msg": msg})
      })
      order.GET("/find", func(context *gin.Context) {
         context.JSON(200, "find")
      })
   }

   err := r.Run("localhost:8083")
   if err != nil {
      fmt.Println("运行失败。。", err)
   }
}

优雅退出

在运行Web服务时,最近强制关闭或者关闭等情况,可以通过信号量对于代码进行优雅退出(即对于一些服务的善后)

func main() {
   r := gin.Default()
   go r.Run(":8080")
   
   // 退出信号量的检测
   quit := make(chan os.Signal)
   signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
   <-quit
   fmt.Println("退出后的一些相关逻辑的处理...")
}

Gin中间件的一些原理

package main

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

func TokenRequired() gin.HandlerFunc {
	return func(context *gin.Context) {
		var token string
		for k, v := range context.Request.Header {
			// 需要用大写,使用x-token 不可
			if k == "X-Token" {
				token = v[0]
			}
		}
		if token != "hsx" {
			context.JSON(http.StatusUnauthorized, gin.H{
				"msg": "未登录",
			})
			//return 不会阻止不访问下面的内容, 需要使用 context.Abort()
			//return
			context.Abort()
		}
		context.Next()
	}
}
func main() {
	r := gin.New()
	r.Use(gin.Logger(), gin.Recovery())
	r.Use(TokenRequired())
	r.GET("/test", func(context *gin.Context) {
		fmt.Println("业务逻辑...")
		context.JSON(200, "data")
	})
	r.Run(":8080")
}

分析

底层的各个Handler,使用的是同级的一个数组存储,当你在当前的Auth使用了return,那么只是跳过了当前的Handler,还是会使用后面的Handler的。而context.Abort()则是直接控制index。所以能达到真正的结束效果。

image.png

编码规范

注解规范

参考文章:Go语言编码规范指导

goland 推荐 使用插件 Goanno,以及一些相关模块推荐

  • Normal Methood

    // ${function_name} , ${todo}
    // @param
    //		${params} , ${todo}
    // @return
    //		${return_types} , ${todo}
    
  • Interface

// ${interface_name} , ${todo}
  • Struct
// ${struct_name} , ${todo}

总结

今天学习到了测试、初步的项目开发、编码规范这三个主要内容

  • 对于测试。首先明白了go的单元测试与Java的不同之处,go对于一些文件的命名和方法的命名是存在规范需要去遵守的,这样才能进行单元测试。同时还是明白了测试的一项很重要的标准:代码覆盖率

  • 对于项目的初步开发,首先我学习到了Gin框架的简单使用,我感觉最重要的一个部分还是Gin对于中间件的一些比较重要的原理,这能避免你踩到一些很严重的坑。也就是在中间件的退出,对于go的中间件,其实可以理解成一个过滤链。在使用过程中,若想跳过所有中间的调研,不能直接使用return,这样只会跳过当前中间件,还会执行后面的中间件。此时需要使用context.Abort()才能达到要求

  • 编码规范。若要编写一个高质量的代码,其中,注解的编写是必不可少