更新14、15和17章目录 (#702)

* 更新14、15和17章目录

* Update README.md

* 添加章节序号

* 添加章节序号

* 添加代码链接

* 修改错别字

* 删除多余字符

* 修复代码与文件不对应的问题

* 修改代码
This commit is contained in:
yusuf
2019-08-02 12:16:20 +08:00
committed by ᴊ. ᴄʜᴇɴ
parent b635a61405
commit b242141e22
7 changed files with 37 additions and 23 deletions

View File

@@ -9,7 +9,7 @@
## 翻译进度
14.9 [实现 Futures 模式](eBook/14.9.md)
18.11 [出于性能考虑的最佳实践和建议](eBook/18.11.md)
## 支持本书

View File

@@ -4,7 +4,7 @@
客户端-服务器应用正是 goroutines 和 channels 的亮点所在。
客户端(Client)可以是运行在任意设备上的任意程序,它会按需发送请求(request)至服务器。服务器(Server)接收到这个请求后开始相应的工作,然后再将响应(response)返回给客户端。典型情况下一般是多个客户端(多个请求对应一个或少量服务器。例如我们日常使用的浏览器客户端其功能就是向服务器请求网页。而Web服务器则会向浏览器响应网页数据。
客户端(Client)可以是运行在任意设备上的任意程序,它会按需发送请求(request)至服务器。服务器(Server)接收到这个请求后开始相应的工作,然后再将响应(response)返回给客户端。典型情况下一般是多个客户端(多个请求对应一个或少量服务器。例如我们日常使用的浏览器客户端其功能就是向服务器请求网页。而Web服务器则会向浏览器响应网页数据。
使用Go的服务器通常会在协程中执行向客户端的响应故而会对每一个客户端请求启动一个协程。一个常用的操作方法是客户端请求自身中包含一个通道而服务器则向这个通道发送响应。
@@ -35,7 +35,7 @@ func run(op binOp, req *Request) {
req.replyc <- op(req.a, req.b)
}
```
`server`协程会无限循环以从`chan \*Request`接收请求,并且为了避免被长时间操作所堵塞,它将为每一个请求启动一个协程来做具体的工作:
`server`协程会无限循环以从`chan *Request`接收请求,并且为了避免被长时间操作所堵塞,它将为每一个请求启动一个协程来做具体的工作:
```go
func server(op binOp, service chan *Request) {
@@ -112,26 +112,22 @@ func run(op binOp, req *Request) {
req.replyc <- op(req.a, req.b)
}
func server(op binOp, service chan *Request, quit chan bool) {
func server(op binOp, service chan *Request) {
for {
select {
case req := <-service:
go run(op, req)
case <-quit:
return
}
req := <-service // requests arrive here
// start goroutine for request:
go run(op, req) // don't wait for op
}
}
func startServer(op binOp) (service chan *Request, quit chan bool) {
service = make(chan *Request)
quit = make(chan bool)
go server(op, service, quit)
return service, quit
func startServer(op binOp) chan *Request {
reqChan := make(chan *Request)
go server(op, reqChan)
return reqChan
}
func main() {
adder, quit := startServer(func(a, b int) int { return a + b })
adder := startServer(func(a, b int) int { return a + b })
const N = 100
var reqs [N]Request
for i := 0; i < N; i++ {
@@ -149,9 +145,9 @@ func main() {
fmt.Println("Request ", i, " is ok!")
}
}
quit <- true
fmt.Println("done")
}
```
## 14.10.2 卸载Teardown通过信号通道关闭服务器

View File

@@ -23,7 +23,7 @@ func DoPart(sem chan int) {
}
func main() {
runtime.GOMAXPROCS = NCPU
runtime.GOMAXPROCS(NCPU) // runtime.GOMAXPROCS = NCPU
DoAll()
}

View File

@@ -117,7 +117,7 @@ func BuildLazyIntEvaluator(evalFunc EvalFunc, initState Any) func() int {
9th even: 18
```
练习14.12general_lazy_evaluation2.go
练习14.12[general_lazy_evaluation2.go](exercises/chapter_14/general_lazy_evalution2.go)
通过使用14.12中工厂函数生成前10个斐波那契数
提示:因为斐波那契数增长很迅速,使用`uint64`类型。

View File

@@ -1,4 +1,4 @@
# defer 模式
# 17.2 defer 模式
使用 `defer` 可以确保资源不再需要时,都会被恰当地关闭或归还到“池子”中。更重要的一点是,它可以恢复 panic。

View File

@@ -1,4 +1,4 @@
# 可见性模式
# 17.3 可见性模式
我们在 [4.2.1节](04.2.md) 见过简单地使用可见性规则控制对类型成员的访问,他们可以是 Go 变量或函数。[10.2.1节](10.2.md) 展示了如何在单独的包中定义类型时,强制使用工厂函数。

View File

@@ -145,12 +145,27 @@
- 14.7 [新旧模型对比任务和worker](14.7.md)
- 14.8 [惰性生成器的实现](14.8.md)
- 14.9 [实现 Futures 模式](14.9.md)
- 14.10 [复用](14.10.md)
- 14.11 [限制同时处理的请求数](14.11.md)
- 14.12 [链式协程](14.12.md)
- 14.13 [在多核心上并行计算](14.13.md)
- 14.14 [并行化大量数据的计算](14.14.md)
- 14.15 [漏桶算法](14.15.md)
- 14.16 [对Go协程进行基准测试](14.16.md)
- 14.17 [使用通道并发访问对象](14.17.md)
- 第15章[网络、模版与网页应用](15.0.md)
- 15.1 [tcp服务器](15.1.md)
- 15.2 [一个简单的web服务器](15.2.md)
- 15.3 [访问并读取页面数据](15.3.md)
- 15.4 [写一个简单的网页应用](15.4.md)
- 15.5 [确保网页应用健壮](15.5.md)
- 15.6 [用模板编写网页应用](15.6.md)
- 15.7 [探索 template 包](15.7.md)
- 15.8 [精巧的多功能网页服务器](15.8.md)
- 15.9 [用 rpc 实现远程过程调用](15.9.md)
- 15.10 [基于网络的通道 netchan](15.10.md)
- 15.11 [与 websocket 通信](15.11.md)
- 15.12 [用 smtp 发送邮件](15.12.md)
## 第四部分:实际应用
@@ -166,7 +181,10 @@
- 16.9 [闭包和协程的使用](16.9.md)
- 16.10 [糟糕的错误处理](16.10.md)
- 第17章[模式](17.0.md)
- 17.1 [关于逗号ok模式](17.1.md)
- 17.1 [逗号ok模式](17.1.md)
- 17.2 [defer 模式](17.2.md)
- 17.3 [可见性模式](17.3.md)
- 17.4 [运算符模式和接口](17.4.md)
- 第18章[出于性能考虑的实用代码片段](18.0.md)
- 18.1 [字符串](18.1.md)
- 18.2 [数组和切片](18.2.md)