不写测试的开发不是好程序员,我个人非常崇拜TDD Test Driven Development 的,然而可惜的是国内的程序员
都不太关注测试这一部分,这篇文章主要介绍下在Go语言中如何做单元测试和基准测试。
go test 工具
Go 语言中的测试依赖go test 命令。编写测试代码和编写普通的Go代码过程是类似的,并不需要学习新的语法。
规则或工具
go test 命令是一个按照一定约定和组织的测试代码的驱动程序,在包目录内,所有以——test,go 为后缀名
的源代码文件都是 go test 测试的一部分,不会被go build 编译到最终的可执行文件中。
在 *_test.go 文件中有三种类型的函数,单元测试函数、基准测试函数和示例函数。
测试函数 函数名前缀为Test 测试程序的一些逻辑行为是否正确
基准函数 函数名前缀为Benchmark 测试函数的性能
示例函数 函数名前缀为Example 为文档提供示例
go test 命令会遍历所有的*_test.go文件汇总符合上述命名规则的函数,然后生成一个临时的main包用于
调用相应的测试函数,然后构建并运行,报告测试结果,最后清理测试中生成的临时文件
Conytext 初识
Go1.7加入了一个新的标准库context,它定义了 Context类型,专门用来简化对于处理单个请求的多个goroutine之间
与请求域的数据,取消信号。截止时间等相关操作,这些操作可能涉及多个API调用。
对服务器传入的请求应该创建上下文,而对服务器的传出调用应该接受上下文。他们之间的函数调用链必须传递上下文,或者可以使用WithCancel WithDeadline
WithTimeout 或WithValue创建的派生上下文,当一个上下文被取消时,它派生的所有上下文也被取消
Context接口
contexty.Context 是一个接口,改接口定义了四个需要实现的方法,具体签名如下:
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <- chan struct{}
Err() error
Value(key interface{}) interface{}
}
其中
Deadline 方法需要返回当前Context被取消的时间,也就是完成工作的截止时间deadline
Done方法需要返回一个Channel ,这个Channel会在当前工作完成或者上下文被取消之后关闭,多次调用
Done方法会范湖同一个Channel;
Err方法会返回当前Context结束的原因,它只会在Done返回的Channel被关闭时才会返回非空的值;
如果当前的Context被取消就会返回Canceled错误;
如果当前Context超时就会返回DeadlineExceeded错误;
Value方法会从Context中返回键对应的值,对于同一个上下文来说,多次调用Value并传入相同的Key
会返回相同的结果,该方法仅用于传递跨API和进程间跟请求域的数据;
Background() 和TODO()
Go内置两个函数:Background()和TODO(),这两个函数分别返回了一个实现了Context接口的background
和todo.我们代码中最开始都是以这两个内置的上下文对象作为最顶层的partent context ,衍生出更多的子
上下文对象。
Background() 主要用于main函数,初始化以及测试代码中,作为Context这个树结构的最顶层的Context,也就是
Context.
TODO() 它目前还不知道具体的使用场景,如果我们不知道该使用什么Context的时候,可以使用这个
background 和 todo 本质上都是emptyCtx 结构体类型,是一个不可取消,没有设置截止时间,没有携带任何值得
Context。
With系列函数
此外,context 包中还定义了四个With系列函数。
WithCancel
返回带有新Done通道的父节点的副本。当调用返回的cancel函数或当关闭父上下文的Done通道时,将关闭返回上下文的Done通道,无论先发生什么情况。
取消此上下文将释放与其关联的资源,因此代码应该在此上下文中运行的操作完成后立即调用cancel
WithDeadline
返回父上下文的副本,并将deadline调整为不迟于d,如果父上下文的deadline已经早于d,则WithDeadline(
parent,d)在语义上等同于父上下文。当截止日过期时,调用返回的cancel函数时,或者当父上下文的Done
通道关闭时,返回上下文的Done通道即将关闭,以最先发生的情况为准。
取消此上下文将释放与其关联的资源,因此代码应该在此上下文中运行的操作完成后立即调用cancel
WithTimeout
取消此上下文将释放与其相关的资源,因此代码应该在此上下文中运行的操作完成后理解调用
cancel,通常用于数据库或者网络连接的超时控制。
WithValue
返回父节点的副本,其中与key关联的值为val.
仅对api和进程间传递请求域的数据使用上下文,而不是使用它来传递可选参数给函数。
所提供的健必须是可以比较的,并且不应该是string类型或任何其他内置类型,以避免使用上下文在包之间
发生冲突。withValue 的用户应该为健定义自己的类型。为了避免在分配给interface {} 时进行分配,上下文
健通常具有具体类型struct{} 。或者,导出的上下文关键变量的静态类型应该是指针或接口。
使用Context的注意事项
推荐以参数的方式显示传递Context
以Context作为参数的函数方法,应该把Context作为第一个参数。
给一个函数方法传递Context的时候,不要传递nil,如果不知道传递什么,就是用context.TODO()
Context的Value相关方法应该传递请求域的必要参数,不应该用于传递可选参数
Context 是线程安全的,可以放心的在多个goroutine 中传递
Zookeeper
是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的
实现,它是集群的管理者,监视者集群中各个节点的状态根据节点提交的反馈进行
下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户