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】协议,转载请保留原文出处及本版权声明。











评论