本文是对前几篇文章的一些补充,主要包含两部分:单元测试和实际项目中使用路由的小问题。

拾遗1:单元测试

Golang单元测试要求代码文件以_test结尾,单元测试方法以Test开头,参数为*testing.T类型。以下是一个计算hash值的工具包和对应的单元测试。

hashUtils.go

  1. package utils
  2. import (
  3. "crypto/md5"
  4. "crypto/sha1"
  5. "fmt"
  6. )
  7. func Md5(str string) string {
  8. data := []byte(str)
  9. has := md5.Sum(data)
  10. return fmt.Sprintf("%X", has)
  11. }
  12. func SHA1(data []byte) []byte {
  13. h := sha1.New()
  14. h.Write(data)
  15. return h.Sum(nil)
  16. }

hashUtils_test.go

  1. package utils
  2. import (
  3. "fmt"
  4. "testing"
  5. )
  6. func TestMd5(t *testing.T) {
  7. content := "123456"
  8. md5 := Md5(content)
  9. if "E10ADC3949BA59ABBE56E057F20F883E" != md5 {
  10. t.Errorf("md5 failed")
  11. }
  12. }
  13. func TestSHA1(t *testing.T) {
  14. content := "123456"
  15. sha1 := fmt.Sprintf("%x", SHA1([]byte(content)))
  16. if "7c4a8d09ca3762af61e59520943dc26494f8941b" != sha1 {
  17. t.Errorf("sha1 failed")
  18. }
  19. }

除了测试这种逻辑代码我们还需要测试HTTP的请求响应。Gin推荐使用net/http/httptest测试HTTP相关的代码。

启动一个Gin服务器main.go

  1. package main
  2. func setupRouter() *gin.Engine {
  3. r := gin.Default()
  4. r.GET("/ping", func(c *gin.Context) {
  5. c.String(200, "pong")
  6. })
  7. return r
  8. }
  9. func main() {
  10. r := setupRouter()
  11. r.Run(":8080")
  12. }

单元测试main_test.go

  1. package main
  2. import (
  3. "net/http"
  4. "net/http/httptest"
  5. "testing"
  6. "github.com/stretchr/testify/assert"
  7. )
  8. func TestPingRoute(t *testing.T) {
  9. router := setupRouter()
  10. w := httptest.NewRecorder()
  11. req, _ := http.NewRequest("GET", "/ping", nil)
  12. router.ServeHTTP(w, req)
  13. assert.Equal(t, 200, w.Code)
  14. assert.Equal(t, "pong", w.Body.String())
  15. }

拾遗2:路由

先看代码

  1. userRouter := router.Group(`users`)
  2. {
  3. userRouter.GET(`/`, userHandler.UserList)
  4. }

我们声明了路由/users/,这是一个Web Api,传入参数的url大概是这样的/users/?pageIndex=1&pageSize=10。用户访问/users?pageIndex=1&pageSize=10时也能正常返回数据,这是因为Gin帮我们做了一次301跳转,问题就出在这里。我们的路由是Web Api用户可能是JS前端,也可能是其他的业务系统。如果用户不支持301跳转呢?

其实我们只要在增加一个空路径路由就可以解决问题。

  1. userRouter := router.Group(`users`)
  2. {
  3. userRouter.GET(``, userHandler.UserList)
  4. userRouter.GET(`/`, userHandler.UserList)
  5. }

现在不管用户访问/users/?pageIndex=1&pageSize=10还是访问/users?pageIndex=1&pageSize=10都会得到正确的结果。

文章出处:基于gin的golang web开发:Gin技术拾遗

基于gin的golang web开发:Gin技术拾遗的更多相关文章

  1. 基于gin的golang web开发:路由

    Gin是一个用Golang编写的HTTP网络框架.它的特点是类似于Martini的API,性能更好.在golang web开发领域是一个非常热门的web框架. 启动一个Gin web服务器 使用下面的 ...

  2. 基于gin的golang web开发:路由二

    在基于gin的golang web开发:路由中我们介绍了Gin的路由和一些获取链接中参数的方法,本文继续介绍其他获取参数的方法. 文件上传 在web开发中文件上传是一个很常见的需求,下面我们来看一下基 ...

  3. 基于gin的golang web开发:模型绑定

    在前两篇文章介绍路由的时候,我们了解到gin可用通过类似DefaultQuery或DefaultPostForm等方法获取到前端提交过来的参数.参数不多的情况下也很好用,但是想想看,如果接口有很多个参 ...

  4. 基于gin的golang web开发:模型验证

    Gin除了模型绑定还提供了模型验证功能.你可以给字段指定特定的规则标签,如果一个字段用binding:"required"标签修饰,在绑定时该字段的值为空,那么将返回一个错误.开发 ...

  5. 基于gin的golang web开发:访问mysql数据库

    web开发基本都离不开访问数据库,在Gin中使用mysql数据库需要依赖mysql的驱动.直接使用驱动提供的API就要写很多样板代码.你可以找到很多扩展包这里介绍的是jmoiron/sqlx.另外还有 ...

  6. 基于gin的golang web开发:使用数据库事务

    在前文介绍访问数据库时介绍了github.com/jmoiron/sqlx包,本文基于这个包使用数据库事务. defer 在使用数据库事务之前,首先需要了解go语言的defer关键字.defer是go ...

  7. 基于gin的golang web开发:mysql增删改查

    Go语言访问mysql数据库需要用到标准库database/sql和mysql的驱动.标准库的Api使用比较繁琐这里再引入另一个库github.com/jmoiron/sqlx. go get git ...

  8. 基于gin的golang web开发:中间件

    gin中间件(middleware)提供了类似于面向切面编程或路由拦截器的功能,可以在请求前和请求之后添加一些自定义逻辑.实际开发中有很多场景会用到中间件,例如:权限验证,缓存,错误处理,日志,事务等 ...

  9. 基于gin的golang web开发:集成swagger

    在前后端分离的项目维护一份完整且及时更新的api文档会极大的提高我们的工作效率,传统项目中接口文档都是由后端开发手写的,这种文档很难保证及时性,久而久之便失去了参考意义.swagger给我们提供了一种 ...

随机推荐

  1. windows下redis的PHP扩展安装

    1.查看已安装PHP的信息,打印phpinfo(); 主要看三个信息:PHP版本,是否线程安全(TS或NTS),系统是x64还是x86.用以确定扩展文件的版本. 2.需要php_redis.dll这个 ...

  2. P2346 四子连棋

    P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...

  3. 数据结构 - 二叉树的遍历(递归VS非递归)

    import java.util.LinkedList; public class BinaryTree { public static void main(String[] args) { int ...

  4. Kubernetes-17:Kubernets包管理工具—>Helm介绍与使用

    Kubernets包管理工具->Helm 什么是Helm? 我们都知道,Linux系统各发行版都有自己的包管理工具,比如Centos的YUM,再如Ubuntu的APT. Kubernetes也有 ...

  5. It is better to have the ability of fast learning

    来自某位大佬: 内功=算法+数据结构+编译原理+操作系统原理+软件工程+英文 十足的自信心+强烈的求知欲+对Programming&&C&&CPP的执着+百折不挠的钻研 ...

  6. C++变量的存储类型

    C++变量和函数包括两个属性:数据类型和数据的存储类型.存储类型是指数据在内存中存储的方式.变量的存储类型分为四种:自动类型(auto),寄存器类型(register).静态类型(static)外部类 ...

  7. C++ 数据结构 2:栈和队列

    1 栈 1.1 栈的基本概念 栈(stack)又名堆栈,它是一种 运算受限的线性表.限定 仅在表尾进行插入和删除操作 的线性表.表尾被称为栈顶,相对地,把另一端称为栈底. 1.1.1 特点 它的特殊之 ...

  8. 后端狗的Vue学习历程(一) - demo示例与基本逻辑语法

    目录 demo的三部分结构 判断:v-if.v-else-if.v-else 循环:v-for 事件绑定 v-on:eventType 内容输入的双向绑定v-model 源码:Github demo的 ...

  9. 纯CSS实现3D正方体动画效果

    前言 纯CSS实现3D正方体动画效果,此方法是通过transform的旋转(rotate)和位移(translate)实现的,具体效果是鼠标滑过时正方体的一个面会产生位移 效果图 ​

  10. tcpack--4延时ack

    TCP在收到数据后必须发送ACK给对端,但如果每收到一个包就给一个ACK的话会使得网络中被注入过多报文.TCP的做法是在收到数据时不立即发送ACK,而是设置一个定时器,如果在定时器超时之前有数据发送给 ...