Skip to content

Commit

Permalink
Merge branch '10.8' of github.com:themoonbear/Mastering_Go_ZH_CN into…
Browse files Browse the repository at this point in the history
… 10.8
  • Loading branch information
themoonbear committed Apr 22, 2019
2 parents 98c993a + 4eed206 commit 7afeb3b
Show file tree
Hide file tree
Showing 8 changed files with 487 additions and 8 deletions.
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 本书翻译接近完成,欢迎阅读GitBook,提出宝贵的修改意见😘。
[Mastering_Go_ZH_CN](https://wskdsgcf.gitbook.io/mastering-go-zh-cn)


# Mastering_Go_ZH_CN
### 《Mastering GO》

Expand Down Expand Up @@ -112,6 +116,7 @@
- [09.3 优雅地结束goroutines](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter9/09.3.md)
- [09.3.1 当Add()和Done()的数量不匹配时会发生什么?](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter9/09.3.1.md)
- [09.4 Channel(通道)](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter9/09.4.md)
- [09.4.1 通道的写入](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter9/09.4.1.md)
- [chapter 10 Go 并发-进阶讨论](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.0.md)
- [10.1 重温调度器](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.1.md)
- [10.1.1 环境变量 GOMAXPROCS](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.1.1.md)
Expand All @@ -132,9 +137,13 @@
- [10.5.3 通过goroutine共享内存](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.5.3.md)
- [10.6 竞争状态](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.6.md)
- [10.7 关于context包](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.7.md)
- [10.7.1 context使用的高级示例](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.7.1.md)

- [10.8 延展阅读](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.8.md)
- [10.9 练习](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.9.md)
- [10.10 本章小结](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter10/10.10.md)


- [chapter 11 代码测试,优化以及分析](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.0.md)
- [11.1 本章使用的Go版本](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.1.md)
- [11.1.1 1.10和1.9的版本对比](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.1.1.md)
Expand All @@ -161,7 +170,7 @@
- [11.13 生成文档](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.13.md)
- [11.14 延展阅读](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.14.md)
- [11.15 练习](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.15.md)
- [11.16 本章小节](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.16.md)
- [11.16 本章小结](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter11/11.16.md)
- [chapter 12 Go网络编程基础](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter12/12.0.md)
- [12.1 关于net/http,net和http.RoundTripper](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter12/12.1.md)
- [12.1.1 http.Response类型](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter12/12.1.1.md)
Expand Down Expand Up @@ -208,14 +217,9 @@
- [13.10 延展阅读](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter13/13.10.md)
- [13.11 练习](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter13/13.11.md)
- [13.12 本章小结](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter13/13.12.md)

-------
### GitBook
[Mastering_Go_ZH_CN](https://wskdsgcf.gitbook.io/mastering-go-zh-cn)

-----
根据翻译进度实时更新。
=======

-------
### 支持本书

Expand Down
65 changes: 65 additions & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* [02.5.1 Go Package](eBook/chapter2/02.5.1.md)
* [02.5.2 C代码](eBook/chapter2/02.5.2.md)
* [02.6 defer关键字](eBook/chapter2/02.6.md)
* [02.7 Panic和Recover](eBook/chapter2/02.7.md)

* [3 Go基本数据类型]
* [03.1 Go循环](eBook/chapter3/03.1.md)
Expand Down Expand Up @@ -105,6 +106,56 @@
* [09.3.1 当Add()和Done()的数量不匹配时会发生什么?](eBook/chapter9/09.3.1.md)
* [09.4 Channel(通道)](eBook/chapter9/09.4.md)

* [10 Go 并发-进阶讨论](eBook/chapter10/10.0.md)
* [10.1 重温调度器](eBook/chapter10/10.1.md)
* [10.1.1 环境变量 GOMAXPROCS](eBook/chapter10/10.1.1.md)
* [10.2 select关键字](eBook/chapter10/10.2.md)
* [10.3 goroutine超时检查的两种方式](eBook/chapter10/10.3.md)
* [10.3.1 方式1](eBook/chapter10/10.3.1.md)
* [10.3.2 方式2](eBook/chapter10/10.3.2.md)
* [10.4 重温Channel(通道)](eBook/chapter10/10.4.md)
* [10.4.1 信号通道](eBook/chapter10/10.4.1.md)
* [10.4.2 可缓冲通道](eBook/chapter10/10.4.2.md)
* [10.4.3 值为nil的通道](eBook/chapter10/10.4.3.md)
* [10.4.4 传送channel的通道](eBook/chapter10/10.4.4.md)
* [10.4.5 指定通道的执行顺序](eBook/chapter10/10.4.5.md)
* [10.5 通过共享变量来共享内存](eBook/chapter10/10.5.md)
* [10.5.1 sync.Mutex类型](eBook/chapter10/10.5.1.md)
* [10.5.1.1 忘记解锁mutex的后果](eBook/chapter10/10.5.1.1.md)
* [10.5.2 sync.RWMutex类型](eBook/chapter10/10.5.2.md)
* [10.5.3 通过goroutine共享内存](eBook/chapter10/10.5.3.md)
* [10.6 竞争状态](eBook/chapter10/10.6.md)
* [10.7 关于context包](eBook/chapter10/10.7.md)

* [11 代码测试,优化及分析](eBook/chapter10/11.0.md)
* [11.1 本章使用的Go版本](eBook/chapter10/11.1.md)
* [11.1.1 1.10和1.9版本对比](eBook/chapter10/11.1.1.md)
* [11.2 安装beta或者RC版本](eBook/chapter10/11.2.md)
* [11.3 关于优化](eBook/chapter10/11.3.md)
* [11.4 优化你的Go代码](eBook/chapter10/11.4.md)
* [11.5 分析Go代码](eBook/chapter10/11.5.md)
* [11.5.1 标准库net/http/pprof](eBook/chapter10/11.5.1.md)
* [11.5.2 代码分析示例](eBook/chapter10/11.5.2.md)
* [11.5.3 用于分析的第三方包](eBook/chapter10/11.5.3.md)
* [11.5.4 Go分析器的web接口](eBook/chapter10/11.5.4.md)
* [11.5.4.1 使用web接口的分析示例](eBook/chapter10/11.5.4.1.md)
* [11.5.4.2 Graphviz快览](eBook/chapter10/11.5.4.2.md)
* [11.6 go tool的代码追踪](eBook/chapter10/11.6.md)
* [11.7 测试](eBook/chapter10/11.7.md)
* [11.7.1 编程测试代码](eBook/chapter10/11.7.1.md)
* [11.8 基准测试](eBook/chapter10/11.8.md)
* [11.8.1 基准测试示例](eBook/chapter10/11.8.1.md)
* [11.8.2 错误的基准测试函数](eBook/chapter10/11.8.2.md)
* [11.9 基准测试的缓冲写入](eBook/chapter10/11.9.md)
* [11.10 揪出隐藏的代码](eBook/chapter10/11.10.md)
* [11.11 交叉编译](eBook/chapter10/11.11.md)
* [11.12 创建示例函数](eBook/chapter10/11.12.md)
* [11.13 生成文档](eBook/chapter10/11.13.md)
* [11.14 延展阅读](eBook/chapter10/11.14.md)
* [11.15 练习](eBook/chapter10/11.15.md)
* [11.16 本章小结](eBook/chapter10/11.16.md)


* [12 Go网络编程基础](eBook/chapter12/12.0.md)
* [12.1 关于net/http,net和http.RoundTripper](eBook/chapter12/12.1.md)
* [12.1.1 http.Response类型](eBook/chapter12/12.1.1.md)
Expand All @@ -115,9 +166,23 @@
* [12.4 命令行工具netcat](eBook/chapter12/12.4.md)
* [12.5 读取网络接口的配置文件](eBook/chapter12/12.5.md)
* [12.6 实现DNS查询](eBook/chapter12/12.6.md)
* [12.6.1 获取域名的 NS记录](eBook/chapter12/12.6.1.md)
* [12.6.2 获取域名的 MX 记录](eBook/chapter12/12.6.2.md)
* [12.7 Go实现web服务器](eBook/chapter12/12.7.md)
* [12.7.1 分析HTTP服务](eBook/chapter12/12.7.1.md)
* [12.7.2 用Go创建网站](eBook/chapter12/12.7.2.md)
* [12.8 追踪 HTTP](eBook/chapter12/12.8.md)
* [12.8.1 测试 HTTP handler](eBook/chapter12/12.8.1.md)
* [12.9 Go实现web客户端](eBook/chapter12/12.9.md)
* [12.9.1 Go web客户端进阶](eBook/chapter12/12.9.1.md)
* [12.10 HTTP连接超时](eBook/chapter12/12.10.md)
* [12.10.1 SetDeadline 介绍](eBook/chapter12/12.10.1.md)
* [12.10.2 服务端设置超时时间](eBook/chapter12/12.10.2.md)
* [12.10.3 设置超时的另外一种方法](eBook/chapter12/12.10.3.md)
* [12.11 抓包工具Wireshark和tshark](eBook/chapter12/12.11.md)
* [12.12 延展阅读](eBook/chapter12/12.12.md)
* [12.13 练习](eBook/chapter12/12.13.md)
* [12.14 本章小结](eBook/chapter12/12.14.md)

* [13 网络编程 - 构建服务器与客户端](eBook/chapter13/13.0.md)
* [13.1 Go 标准库-net](eBook/chapter13/13.1.md)
Expand Down
202 changes: 202 additions & 0 deletions eBook/chapter10/10.7.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# context使用的高级示例

使用 `useContext.go` 程序代码将更好,更深入的说明 `context` 包的功能,该代码分为五部分来介绍。

这个例子中,您将创建一个快速响应的 HTTP 客户端,这是一个很常见的需求。事实上,几乎所有的 HTTP 客户端都支持这个功能,您将学习另一个 HTTP 请求超时的技巧,在[第12章](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter12/12.0.md)(Go网络编程基础)。

`useContext.go` 程序需要两个命令行参数:要连接的服务器 URL 和应该等待的延迟。如果该程序只有一个命名行参数,那么延迟将是 5 秒。

`useContext.go` 的第一段代码如下:

```go
package main

import (
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"sync"
"time"
)

var (
myUrl string
delay int = 5
w sync.WaitGroup
)

type myData struct {
r *http.Response
err error
}
```

`myUrl``delay` 都是全局变量,因此它们能从代码的任意位置访问。另外,有一个名为 `w``sync..WaitGroup` 变量也是全局的,还有一个名为 `myData` 的结构体用于把 web 服务器的响应和一个错误变量绑在一起。

`useContext.go` 的第二部分代码如下:

```go
func connect(c context.Context) error {
defer w.Done()
data := make(chan myData, 1)
tr := &http.Transport{}
httpClient := &http.Client{Transport: tr}

req, _ := http.NewRequest("GET", myUrl, nil)
```
上面的代码处理 HTTP 连接。
> 您会了解更多关于开发 web 服务器和客户端的内容,在[第12章](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/eBook/chapter12/12.0.md)(Go网络编程基础)。
`useContext.go` 的第三段代码如下:
```go
go func() {
response, err := httpClient.Do(req)
if err != nil {
fmt.Println(err)
data <- myData{nil, err}
return
} else {
pack := myData{response, err}
data <- pack
}
}()
```
`useContext.go` 的第四段代码如下:
```go
select {
case <-c.Done():
tr.CancelRequest(req)
<-data
fmt.Println("The request was cancelled!")
return c.Err()
case ok := <-data:
err := ok.err
resp := ok.r
if err != nil {
fmt.Println("Error select:", err)
return err
}
defer resp.Body.Close()

realHTTPData, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error select:", err)
return err
}
fmt.Println("Server Response: %s\n", realHTTPData)
}
return nil
}
```

`useContext.go` 的其余代码实现了 `main()` 函数,如下:

```go
func main() {
if len(os.Args) == 1 {
fmt.Println("Need a URL and a delay!")
return
}

myUrl = os.Args[1]
if len(os.Args) == 3 {
t. err := strconv.Atoi(os.Args[2])
if err != nil {
fmt.Println(err)
return
}
delay = t
}

fmt.Println("Delay:", delay)
c := context.Background()
c, cancel := contedxt.WithTimeout(c, time.Duration(delay)*time.Second)
defer cancel()

fmt.Printf("Connecting to %s \n", myUrl)
w.Add(1)
go connect(c)
w.Wait()
fmt.Println("Exiting...")
}
```

`context.WithTimeout()` 方法定义了超时期限。`connect()` 函数作为一个 goroutine 执行,将会正常终止或 `cancel()` 函数执行时终止。

尽管没必要知道服务端的操作,但看一下 Go 版本的随机减速的 web 服务器也是好的;一个随机数生成器决定您的 web 服务器有多慢。`slowWWW.go` 的源码内容如下:

```go
package main

import (
"fmt"
"math/rand"
"net/http"
"os"
"time"
)

func random(min, max int) int {
return rand.Intn(max-min) + min
}

func myHandler(w http.ResponseWriter, r *http.Request) {
delay := random(0, 15)
time.Sleep(time.Duration(delay) * time.Second)

fmt.Fprintf(w, "Servring: %s\n", r.URL.Path)
fmt.Fprintf(w, "Dealy: %d\n", delay)
fmt.Printf("Served: %s\n", r.Host)
}

func main() {
seed := time.Now().Unix()
rand.Seed(seed)

PORT := ":8001"
arguments := os.Args
if len(arguments) == 1 {
fmt.Println("Using default port nubmer: ", PORT)
} else {
PORT = ":" + arguments[1]
}

http.HandleFunc("/", myHandler)
err := http.ListenAndServer(PORT, nil)
if err != nil {
fmt.Println(err)
os.Exit(10)
}
}
```

如您所见,您不需要在 `slowWWW.go` 文件中使用 `context` 包,因为那是 web 客户端的工作,它会决定需要多长时间等待响应。

`myHandler()` 函数的代码负责 web 服务器的减速处理。如介绍的那样,延迟可以由 `random(0,15)` 函数在 0 到 14 秒随机产生。

如果您使用如 `wget(1)` 的工具访问 `slowWWW.go` 服务器的话,会收到如下输出:

```shell
$wget -qO- http://localhost:8001/
Serving: /
Delay: 4
$wget -qO- http://localhost:8001/
Serving: /
Delay: 13
```

这是因为 `wget(1)` 的默认超时时间比较大。

`slowWWW.go` 已经在另一个 Unix shell 里运行后,用方便的 `time(1)` 工具处理执行 `useContext.go` 的输出如下:

![""](https://github.com/hantmac/Mastering_Go_ZH_CN/tree/master/images/chapter10/10.7.1.jpg)

这个输出显示只有第三个命令确实从 HTTP 服务器获得了响应——第一和第二个命令都超时了!
Loading

0 comments on commit 7afeb3b

Please sign in to comment.