勘误表

《Go 程序员面试笔试宝典》勘误表 #

请直接搜索对应的页面,如“第 255 页”,查看该页面的勘误内容。

第 V 页 #

  • typo 4.3 通道的底结构 -> 通道的底层结构。

第 9 页 #

  • 多了一个逗号
image
  • 少了一个括号
image

第 13 页 #

  • 调用 deferproc 函数
image

第 22 页 #

  • 3.1.2 节,“再次向 S2 追加元素 200”一句下方的代码应为 s2 = append(s2, 200),原文误写为 s2 = append(s2, 100)。(本站在线版已是正确的 200。)

第 27 页 #

  • 形参是实参的一个复制
image

第 32 页 #

  • s/hamp/hmap
image

第 35 页 #

  • 返回 value 类型的零值
image

第 64 页 #

  • 图 4-3 描述有误
image

第 73 页 #

  • 示例代码和运行结果修正

示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type Student struct {
	name string
	age  int
}

var s = Student{name: "qcrao", age: 18}
var g = &s

func modifyUser(pu *Student) {
	fmt.Println("modifyUser received value:", pu)
	pu.name = "Old Old qcrao"
	pu.age = 200
}

func printUser(u <-chan *Student) {
	time.Sleep(2 * time.Second)
	fmt.Println("printUser get:", <-u)
}

func main() {
	c := make(chan *Student, 5)
	c <- g
	fmt.Println(g)
	// modify g
	g = &Student{name: "Old qcrao", age: 100}
	go printUser(c)
	go modifyUser(g)
	time.Sleep(5 * time.Second)
	fmt.Println(g)
}

运行结果:

1
2
3
4
&{qcrao 18}
modifyUser received value: &{Old qcrao 100}
printUser get: &{qcrao 18}
&{Old Old qcrao 200}
  • 图中变量标注有误:
image

第 76 页 #

  • IsClosed 函数返回 false
image

第 89 页 #

  • 多余的“个”
image

第 112 页 #

  • 当 n==5 时,描述有问题
image

第 113 页 #

  • context 包代码结构功能表格描述有问题
image

第 117 页 #

image

第 122 页 #

  • 多了一个 String 方法的代码
image

第 131 页 #

  • 去掉多余的描述
image

第 132 页 #

  • errors.Aserrors.Is 的描述有误(二者不要混淆):

    • errors.Is(err, target):沿错误链判断是否存在与 目标值 target 相等(或其 Is 方法返回 true)的错误,用于与哨兵错误(sentinel error)做比较。
    • errors.As(err, target):沿错误链找到第一个可以赋值给 target 所指向 类型 的错误,并把它赋值给 targettarget 必须是非空指针)。它匹配的是类型,而不是值。

    因此原文“As 从 err 错误链里找到第一个和 target 相等的值并设置为 target”描述的其实是 Is 的“按值比较”语义;As 应描述为“按类型匹配并赋值”。

第 141 页 #

  • 有关 interface 的章节说明有误
image

第 174 页 #

  • 图标注有误
image

第 186 页 #

  • 关于 M 的描述有误:
image

上面红框内的这两段话替换为:

Go 调度循环可以看成是一个“生产-消费”的流程。

生产端就是我们写的 go func()…语句,它会产生一个 goroutine。消费者是 M,所有的 M 都是在不断地执行调度循环:找到 runnable 的 goroutine 来运行,运行完了就去找下一个 goroutine……

P 的个数是固定的,它等于 GOMAXPROCS 个,进程启动的时候就会被全部创建出来。随着程序的运行,越来越多的 goroutine 会被创建出来。这时,M 也会随之被创建,用于执行 goroutine,M 的个数没有一定的规律,视 goroutine 情况而定。

  • 多了个“不”字
image

第 191 页 #

  • memory 拼写错误
image

第 192 页 #

  • s/_Grunnale/_Grunnable
image

第 201 页 #

  • typo:图中“BX 存器里面现在放的是当前 g 结构体对象的地址”应为“BX 存器”,漏了一个“寄”字。

第 211 页 #

  • 图 12-19 m0 标识错误
image

第 235 页 #

  • notewakeup 唤醒
image

第 240 页 #

  • 12.14.1 小节中,“这时和 P 绑定的 G 正在进行系统调用,无法执行其他的 G” 更改为 “这时和 P 绑定的 M 正在进行系统调用,无法执行其他的 G”

第 255 页 #

  • 图 13-3 标识错误,如下图
image

第 258 页 #

  • 表 13-1 不同等级的浪费”下方算式错误
image

第 279 页 #

  • 该页最后引用的 Go 仓库 Issue 编号有误,应为 golang/go#42430,原文误写为 #43430。

第 288 页 #

  • A.ref1 = nil 描述有误:根据图示 A.ref1 = B,应为“移除灰色对象 A 对白色对象 B 的引用(ref1)”,原文误写为(ref2)。

第 290~291 页 #

  • 图 14-16(Dijkstra 写屏障):Dijkstra(C.ref3, C.ref2,ref1) 中的逗号应为点号,即 Dijkstra(C.ref3, C.ref2.ref1)
  • Yuasa 写屏障对应的图:Yuasa(A.ref3, B) 应为 Yuasa(C.ref3, B)

(本站在线版《垃圾回收的认识》一节中相应的文字描述使用的是 C.ref2.ref1C.ref3,可作对照。)

第 292 页 #

  • 步调算法下界描述有误:从 Go 1.14 开始 $h_t$ 增加的下界应为 $0.6 \rho$(即 0.6 * gcpercent/100),与上界 $0.95 \rho$ 同样按 $\rho$ 缩放,原文写作“下界 0.6”。在默认 GOGC=100($\rho=1$)时下界数值恰为 0.6。参见 go1.14 runtime/mgc.gogcSetTriggerRatiominTriggerRatio := 0.6 * scalingFactor

第 298 页 #

  • GC 时间降到 300us
image

第 306 页 #

  • 图 14-19 标识错误
image ---
最后更新:2026.06.06