learn go with tests 学习笔记(六)进程同步
知识点
net/http/httptest
在标准库中有一个 net/http/httptest 包,它可以让你轻易建立一个 HTTP 模拟服务器(mock HTTP server)。
我们改为使用模拟测试,这样我们就可以控制可靠的服务器来测试了。
httptest.NewServer
接受一个我们传入的 *匿名函数* http.HandlerFunc
。
http.HandlerFunc
是一个看起来类似这样的类型:type HandlerFunc func(ResponseWriter, *Request)
。
这些只是说它是一个需要接受一个 ResponseWriter
和 Request
参数的函数,这对于 HTTP 服务器来说并不奇怪。
结果呢,这里并没有什么彩蛋,这也是如何在 Go 语言写一个 **真实的** HTTP 服务器的方法。唯一的区别就是我们把它封装成一个易于测试的 httptest.NewServer
,它会找一个可监听的端口,然后测试完你就可以关闭它了。
我们让两个服务器中慢的那一个短暂地 time.Sleep
一段时间,当我们请求时让它比另一个慢一些。然后两个服务器都会通过 w.WriteHeader(http.StatusOK)
返回一个 OK
给调用者。
defer
在某个函数调用前加上 defer
前缀会在 包含它的函数结束时 调用它。
有时你需要清理资源,例如关闭一个文件,在我们的案例中是关闭一个服务器,使它不再监听一个端口。
你想让它在函数结束时执行(关闭服务器),但要把它放在你创建服务器语句附近,以便函数内后面的代码仍可以使用这个服务器。
进程同步
示例代码:
(一)ping
我们定义了一个可以创建 chan bool
类型并返回它的 ping
函数。
在这个案例中,我们并不 关心 channel 中发送的类型, 我们只是想发送一个信号 来说明已经发送完了,所以返回 bool 就可以了。
同样在这个函数中,当我们完成 http.Get(url)
时启动了一个用来给 channel 发送信号的 Go 程(goroutine)。
(二)select
如果你记得并发那一章的内容,你可以通过 myVar := <-ch
来等待值发送给 channel。这是一个 阻塞 的调用,因为你需要等待值返回。
select
则允许你同时在 多个 channel 等待。第一个发送值的 channel「胜出」,case
中的代码会被执行。
我们在 select
中使用 ping
为两个 URL
设置两个 channel。无论哪个先写入其 channel 都会使 select
里的代码先被执行,这会导致那个 URL
先被返回(胜出)。
如此一来,进程同步实现起来非常简单。
引用
版权声明: 本文为 InfoQ 作者【半亩房顶】的原创文章。
原文链接:【http://xie.infoq.cn/article/43f75af0cf55d6c4e4c365451】。
本文遵守【CC BY-NC】协议,转载请保留原文出处及本版权声明。
评论