Browse Source

Fix 14.5, 14.6, 15.1 (#283)

* Update 07.3.md

* Update 07.3.md

* Update 07.6.md

* fix few problems

* Update 10.6 and 10.8

* Update 11.6 and 11.7

* fix some problems before Chap13

* add a dot

* Update 13.9

* little improve

* Thoughts about time.After

* Thoughts about time.After

* Fix 14.6,15.1
王耀 1 year ago
parent
commit
f2a3e873fe

+ 17 - 2
eBook/14.5.md

@@ -137,7 +137,7 @@ select {
137 137
 
138 138
 第二种形式:取消耗时很长的同步调用
139 139
 
140
-也可以使用 `time.After()` 函数替换 `timeout-channel`。可以在 `select` 中使用以发送信号超时或停止协程的执行。以下代码,在 `timeoutNs` 纳秒后执行 `select` 的 `timeout` 分支时,`client.Call` 不会给通道 `ch` 返回值:
140
+也可以使用 `time.After()` 函数替换 `timeout-channel`。可以在 `select` 中通过 `time.After()` 发送的超时信号来停止协程的执行。以下代码,在 `timeoutNs` 纳秒后执行 `select` 的 `timeout` 分支后,执行`client.Call` 的协程也随之结束,不会给通道 `ch` 返回值:
141 141
 
142 142
 ```go
143 143
 ch := make(chan error, 1)
@@ -151,7 +151,22 @@ case <-time.After(timeoutNs):
151 151
 }
152 152
 ```
153 153
 
154
-注意缓冲大小设置为 1 是必要的,可以避免协程死锁以及确保超时的通道可以被垃圾回收。
154
+注意缓冲大小设置为 1 是必要的,可以避免协程死锁以及确保超时的通道可以被垃圾回收。此外,需要注意在有多个 `case` 符合条件时, `select` 对 `case` 的选择是伪随机的,如果上面的代码稍作修改如下,则 `select` 语句可能不会在定时器超时信号到来时立刻选中 `time.After(timeoutNs)` 对应的 `case`,因此协程可能不会严格按照定时器设置的时间结束。
155
+
156
+```go
157
+ch := make(chan int, 1)
158
+go func() { for { ch <- 1 } } ()
159
+L:
160
+for {
161
+    select {
162
+    case <-ch:
163
+        // do something
164
+    case <-time.After(timeoutNs):
165
+        // call timed out
166
+        break L
167
+    }
168
+}
169
+```
155 170
 
156 171
 第三种形式:假设程序从多个复制的数据库同时读取。只需要一个答案,需要接收首先到达的答案,`Query` 函数获取数据库的连接切片并请求。并行请求每一个数据库并返回收到的第一个响应:
157 172
 

File diff suppressed because it is too large
+ 1 - 1
eBook/14.6.md


File diff suppressed because it is too large
+ 5 - 5
eBook/15.1.md


+ 2 - 2
eBook/examples/chapter_15/server.go

@@ -27,11 +27,11 @@ func main() {
27 27
 func doServerStuff(conn net.Conn) {
28 28
 	for {
29 29
 		buf := make([]byte, 512)
30
-		_, err := conn.Read(buf)
30
+		len, err := conn.Read(buf)
31 31
 		if err != nil {
32 32
 			fmt.Println("Error reading", err.Error())
33 33
 			return //终止程序
34 34
 		}
35
-		fmt.Printf("Received data: %v", string(buf))
35
+		fmt.Printf("Received data: %v", string(buf[:len]))
36 36
 	}
37 37
 }

+ 2 - 2
eBook/examples/chapter_15/simple_tcp_server.go

@@ -4,8 +4,8 @@ package main
4 4
 import (
5 5
 	"flag"
6 6
 	"fmt"
7
-	"os"
8 7
 	"net"
8
+	"os"
9 9
 )
10 10
 
11 11
 const maxRead = 25
@@ -27,7 +27,7 @@ func main() {
27 27
 func initServer(hostAndPort string) *net.TCPListener {
28 28
 	serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)
29 29
 	checkError(err, "Resolving address:port failed: '"+hostAndPort+"'")
30
-	listener, err := net.ListenTCP("tcp", serverAddr)
30
+	listener, err := net.Listen("tcp", serverAddr)
31 31
 	checkError(err, "ListenTCP: ")
32 32
 	println("Listening to: ", listener.Addr().String())
33 33
 	return listener

+ 1 - 1
eBook/examples/chapter_15/simple_tcp_server_v1.go

@@ -26,7 +26,7 @@ func main() {
26 26
 func initServer(hostAndPort string) *net.TCPListener {
27 27
 	serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)
28 28
 	checkError(err, "Resolving address:port failed: '"+hostAndPort+"'")
29
-	listener, err := net.ListenTCP("tcp", serverAddr)
29
+	listener, err := net.Listen("tcp", serverAddr)
30 30
 	checkError(err, "ListenTCP: ")
31 31
 	println("Listening to: ", listener.Addr().String())
32 32
 	return listener