mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2024-11-28 00:58:54 +00:00
Compare commits
6 Commits
561b2d100a
...
1597ed7bcd
Author | SHA1 | Date | |
---|---|---|---|
|
1597ed7bcd | ||
|
b4c6e3e234 | ||
|
eaef4fd12d | ||
|
380ff85241 | ||
|
414ff02cea | ||
|
f6bb64ce09 |
@ -71,7 +71,7 @@ s[0] = 'L' // compile error: cannot assign to s[0]
|
|||||||
字符串值也可以用字符串面值方式编写,只要将一系列字节序列包含在双引号内即可:
|
字符串值也可以用字符串面值方式编写,只要将一系列字节序列包含在双引号内即可:
|
||||||
|
|
||||||
```
|
```
|
||||||
"Hello, 世界"
|
"Hello, world"
|
||||||
```
|
```
|
||||||
|
|
||||||
![](../images/ch3-04.png)
|
![](../images/ch3-04.png)
|
||||||
|
@ -17,7 +17,7 @@ func Parse(input string) (s *Syntax, err error) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
deferred函数帮助Parse从panic中恢复。在deferred函数内部,panic value被附加到错误信息中;并用err变量接收错误信息,返回给调用者。我们也可以通过调用runtime.Stack往错误信息中添加完整的堆栈调用信息。
|
recover函数帮助Parse从panic中恢复。在deferred函数内部,panic value被附加到错误信息中;并用err变量接收错误信息,返回给调用者。我们也可以通过调用runtime.Stack往错误信息中添加完整的堆栈调用信息。
|
||||||
|
|
||||||
不加区分的恢复所有的panic异常,不是可取的做法;因为在panic之后,无法保证包级变量的状态仍然和我们预期一致。比如,对数据结构的一次重要更新没有被完整完成、文件或者网络连接没有被关闭、获得的锁没有被释放。此外,如果写日志时产生的panic被不加区分的恢复,可能会导致漏洞被忽略。
|
不加区分的恢复所有的panic异常,不是可取的做法;因为在panic之后,无法保证包级变量的状态仍然和我们预期一致。比如,对数据结构的一次重要更新没有被完整完成、文件或者网络连接没有被关闭、获得的锁没有被释放。此外,如果写日志时产生的panic被不加区分的恢复,可能会导致漏洞被忽略。
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
相反,一个goroutine会以一个很小的栈开始其生命周期,一般只需要2KB。一个goroutine的栈,和操作系统线程一样,会保存其活跃或挂起的函数调用的本地变量,但是和OS线程不太一样的是,一个goroutine的栈大小并不是固定的;栈的大小会根据需要动态地伸缩。而goroutine的栈的最大值有1GB,比传统的固定大小的线程栈要大得多,尽管一般情况下,大多goroutine都不需要这么大的栈。
|
相反,一个goroutine会以一个很小的栈开始其生命周期,一般只需要2KB。一个goroutine的栈,和操作系统线程一样,会保存其活跃或挂起的函数调用的本地变量,但是和OS线程不太一样的是,一个goroutine的栈大小并不是固定的;栈的大小会根据需要动态地伸缩。而goroutine的栈的最大值有1GB,比传统的固定大小的线程栈要大得多,尽管一般情况下,大多goroutine都不需要这么大的栈。
|
||||||
|
|
||||||
** 练习 9.4:** 创建一个流水线程序,支持用channel连接任意数量的goroutine,在跑爆内存之前,可以创建多少流水线阶段?一个变量通过整个流水线需要用多久?(这个练习题翻译不是很确定)
|
**练习 9.4:** 创建一个流水线程序,支持用channel连接任意数量的goroutine,在跑爆内存之前,可以创建多少流水线阶段?一个变量通过整个流水线需要用多久?(这个练习题翻译不是很确定)
|
||||||
|
|
||||||
### 9.8.2. Goroutine调度
|
### 9.8.2. Goroutine调度
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ Go的运行时包含了其自己的调度器,这个调度器使用了一些技
|
|||||||
|
|
||||||
和操作系统的线程调度不同的是,Go调度器并不是用一个硬件定时器,而是被Go语言“建筑”本身进行调度的。例如当一个goroutine调用了time.Sleep,或者被channel调用或者mutex操作阻塞时,调度器会使其进入休眠并开始执行另一个goroutine,直到时机到了再去唤醒第一个goroutine。因为这种调度方式不需要进入内核的上下文,所以重新调度一个goroutine比调度一个线程代价要低得多。
|
和操作系统的线程调度不同的是,Go调度器并不是用一个硬件定时器,而是被Go语言“建筑”本身进行调度的。例如当一个goroutine调用了time.Sleep,或者被channel调用或者mutex操作阻塞时,调度器会使其进入休眠并开始执行另一个goroutine,直到时机到了再去唤醒第一个goroutine。因为这种调度方式不需要进入内核的上下文,所以重新调度一个goroutine比调度一个线程代价要低得多。
|
||||||
|
|
||||||
** 练习 9.5: ** 写一个有两个goroutine的程序,两个goroutine会向两个无buffer channel反复地发送ping-pong消息。这样的程序每秒可以支持多少次通信?
|
**练习 9.5:** 写一个有两个goroutine的程序,两个goroutine会向两个无buffer channel反复地发送ping-pong消息。这样的程序每秒可以支持多少次通信?
|
||||||
|
|
||||||
### 9.8.3. GOMAXPROCS
|
### 9.8.3. GOMAXPROCS
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ $ GOMAXPROCS=2 go run hacker-cliché.go
|
|||||||
|
|
||||||
在第一次执行时,最多同时只能有一个goroutine被执行。初始情况下只有main goroutine被执行,所以会打印很多1。过了一段时间后,GO调度器会将其置为休眠,并唤醒另一个goroutine,这时候就开始打印很多0了,在打印的时候,goroutine是被调度到操作系统线程上的。在第二次执行时,我们使用了两个操作系统线程,所以两个goroutine可以一起被执行,以同样的频率交替打印0和1。我们必须强调的是goroutine的调度是受很多因子影响的,而runtime也是在不断地发展演进的,所以这里的你实际得到的结果可能会因为版本的不同而与我们运行的结果有所不同。
|
在第一次执行时,最多同时只能有一个goroutine被执行。初始情况下只有main goroutine被执行,所以会打印很多1。过了一段时间后,GO调度器会将其置为休眠,并唤醒另一个goroutine,这时候就开始打印很多0了,在打印的时候,goroutine是被调度到操作系统线程上的。在第二次执行时,我们使用了两个操作系统线程,所以两个goroutine可以一起被执行,以同样的频率交替打印0和1。我们必须强调的是goroutine的调度是受很多因子影响的,而runtime也是在不断地发展演进的,所以这里的你实际得到的结果可能会因为版本的不同而与我们运行的结果有所不同。
|
||||||
|
|
||||||
** 练习9.6:** 测试一下计算密集型的并发程序(练习8.5那样的)会被GOMAXPROCS怎样影响到。在你的电脑上最佳的值是多少?你的电脑CPU有多少个核心?
|
**练习9.6:** 测试一下计算密集型的并发程序(练习8.5那样的)会被GOMAXPROCS怎样影响到。在你的电脑上最佳的值是多少?你的电脑CPU有多少个核心?
|
||||||
|
|
||||||
### 9.8.4. Goroutine没有ID号
|
### 9.8.4. Goroutine没有ID号
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user