Giter Club home page Giter Club logo

cloud-native-go's People

Contributors

rainbowmango avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

cloud-native-go's Issues

[勘误]反馈一个第12章第3节replace指令行为的描述

问题描述
go.mod中replace指令=>右侧是本地目录时,左侧可以不指定版本号。

如何找到这个错误

  • 章节:12.3.3-1
  • 页码:326

您认为应该如何?

-replace指令中“=>”前面的包及其版本号必须出现在……
+如果replace指令中“=>”右侧是本地目录,左侧可以不指定版本号。否则“=>”前面的包及其版本号必须出现在……

图片
image

12.3.3-4中有一个例子就使用了本地路径,且省略了"=>"左侧的版本号
image

[勘误]反馈一个第13章第3节的错别字

问题描述
A clear and concise description of what the bug is.

如何找到这个错误

  • 章节:12.3.4-2
  • 页码:331

您认为应该如何?
缺少空格

-modulegithub.com/renhongcai/exclude
+module github.com/renhongcai/exclude

图片
image


如何找到这个错误

  • 章节:12.3.12-1
  • 页码:355

您认为应该如何?
缺少空格

-GOSUMDB="<checksum database name>+<publickey><checksum service URL>"
+GOSUMDB="<checksum database name>+<public key> <checksum service URL>"

图片
image


如何找到这个错误

  • 章节:12.3.13-3-1
  • 页码:364, 366

您认为应该如何?
GOSUMDB树最底层的节点有时说成“树的根部”,容易引起误解,误以为最顶层的根节点。不如就按前文叫“底层节点”,或者叫“叶子节点”也可以。

图片
image
image


如何找到这个错误

  • 章节:12.3.11-2-6

  • 页码:351

  • 章节:12.3.13-3-1

  • 页码:364-366

您认为应该如何?
有些地方包名用 go.dog开头,例如go.dog/uuid,这是有意为之吗?

图片
image
image
image


如何找到这个错误

  • 章节:12.3.16
  • 页码:372

您认为应该如何?
缺少点号

- 1 Go 1.11
+1. Go 1.11

图片
image

[勘误]第8章第3节嵌套panic示例代码逻辑遗漏

问题描述
当defer中再次引发panic,应该跳过该defer函数的执行,而不是尝试再次执行。

如何找到这个错误

  • 章节:8.3.3-3-3
  • 页码:251

您认为应该如何?

 if d.started {
         if d._panic != nil {
                 d._panic.aborted = true
         }
         d._panic = nil
+        d.fn = nil
+        gp._defer = d.link
+        freedefer(d)
+        continue
 }
 d.started = true
 d._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
 reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
 
+d._panic = nil
 d.fn = nil
 gp._defer = d.link

以上逻辑参考了go源码src/runtime/panic.go:gopanic

图片
image

其他补充信息

[勘误]反馈一个第1章第1.3.3节中map扩容条件的问题

问题描述
触发扩容条件中的第2项:overflow的数量大于2^15,即overflow数量超过32768
看源码应该是overflow的数量大于等于 2^min(15,B)

func tooManyOverflowBuckets(noverflow uint16, B uint8) bool {
	// If the threshold is too low, we do extraneous work.
	// If the threshold is too high, maps that grow and shrink can hold on to lots of unused memory.
	// "too many" means (approximately) as many overflow buckets as regular buckets.
	// See incrnoverflow for more details.
	if B > 15 {
		B = 15
	}
	// The compiler doesn't see here that B < 16; mask B to generate shorter shift code.
	return noverflow >= uint16(1)<<(B&15)
}

如何找到这个错误

  • 章节:1.3.3
  • 页码:32

您认为应该如何?
应该为:overflow的数量大于等于 2^min(15,B)

其他补充信息
问题描述
触发扩容条件中的第2项:overflow的数量大于2^15,即overflow数量超过32768
看源码应该是overflow的数量大于等于 2^min(15,B)

func tooManyOverflowBuckets(noverflow uint16, B uint8) bool {
	// If the threshold is too low, we do extraneous work.
	// If the threshold is too high, maps that grow and shrink can hold on to lots of unused memory.
	// "too many" means (approximately) as many overflow buckets as regular buckets.
	// See incrnoverflow for more details.
	if B > 15 {
		B = 15
	}
	// The compiler doesn't see here that B < 16; mask B to generate shorter shift code.
	return noverflow >= uint16(1)<<(B&15)
}

如何找到这个错误

  • 章节:1.3.3
  • 页码:32

您认为应该如何?
应该为:overflow的数量大于等于 2^min(15,B)

其他补充信息
https://github.com/golang/go/blob/go1.16.12/src/runtime/map.go#L1074-L1087

[勘误]反馈一个第10章第1节的错别字

问题描述
A clear and concise description of what the bug is.

如何找到这个错误

  • 章节:10.1.1
  • 页码:294

您认为应该如何?

-但并代表大家对它有深刻的认识
+但并不代表大家对它有深刻的认识

图片
1

其他补充信息

[勘误]chan目录代码注解有矛盾

问题描述
exam.go:88行 // 写nil管道不会阻塞
exam_test.go: 31行 // 写nil管道会阻塞,不能添加期望值

您认为应该如何?
两者之间是否有矛盾呢?读写nil管道都会阻塞吧

图片
如果有可能,尽量提供图片。

其他补充信息

[勘误]第7章错别字和笔误

7.1.3节-4

第162页

-检测多行输出格式为// Output: \ <期望字符串> \ <期望字符串>
-检测无序输出格式为// Unordered output: \ <期望字符串> \ <期望字符串>
+检测多行输出格式为// Output: \n <期望字符串> \n <期望字符串>
+检测无序输出格式为// Unordered output: \n <期望字符串> \n <期望字符串>

image

7.3.6节-2

第196页

-可通过参数timeout <n>指定
+可通过参数-timeout <n>指定

image

7.3.6节-3

第196页

-性能测试:runExamples
-示例测试:runBenchmarks
+性能测试:runBenchmarks
+示例测试:runExamples

image

7.4.2节-1

第205页

--count=N参数可以指定执行benchmarkN次
+-count=N参数可以指定执行benchmark N次

image

关于13.1节的疑问

问题描述
13.1节的内容感觉有点多余,因为13.3节已经解析到append时值传递所以不可能操作原来的slice,那13.1节分析的扩容感觉不是问题所在,即使不扩容,只要不接收返回返回值,原来的slice也是不会变化。

关于书中for...range <string>语法第二个返回值的说明似乎有误

在用for...range迭代string时,range返回的第二个值是rune类型,其内容为对应字符的(完整的)Unicode码点。不过书中一直说是Unicode编码的首字节,而不是全部。

Go语言规范中的说法也是Unicode码点:https://golang.org/ref/spec#For_range

For a string value, the "range" clause iterates over the Unicode code points in the string starting at byte index 0. On successive iterations, the index value will be the index of the first byte of successive UTF-8-encoded code points in the string, and the second value, of type rune, will be the value of the corresponding code point.

书中涉及之处有:

2.2.2节-3

第78页

range作用于string时……元素值是该字符对应的Unicode编码的首个字节的值

image

第79页

range的第二个返回值的类型为rune类型,它仅代表Unicode编码的1个字节

image

2.2.3节-3

第83页

返回的元素值为rune类型的单个字节值……该字节值仅代表Unicode编码的首个字节

image

[勘误]反馈一个第1章第1节的管道的问题

问题描述
管道关闭后获取的数据为零值。

如何找到这个错误

  • 章节:1.1.3-2-4
  • 页码:10

您认为应该如何?

-这些协程获取的数据都为nil。
+这些协程获取的数据都为对应类型的零值。

图片
image

其他补充信息

第2章错别字和笔误

2.1.3节-2-3

第73页

-循环变量各个case时,循环能正常结束
+循环遍历各个case时,循环能正常结束

2.2.1节-2-4

第77页

题目四

-本题答案为D。
+本题答案为C。

2.2.2节

第77页

-由于range可以给循环变量赋值,使其起来好像函数返回一样
+由于range可以给循环变量赋值,使其看起来好像函数返回一样

[勘误]反馈一个第8章第2节的错别字

问题描述
语句不通顺

如何找到这个错误

  • 章节:8.2.4-1
  • 页码:237

您认为应该如何?

-同时编译还会在函数尾部插入deferreturn函数
+同时编译器还会在函数尾部插入deferreturn函数
-运行时中协程g的数据结构如下:
+运行时协程中g的数据结构如下:

图片
image

如何找到这个错误

  • 章节:8.2.4-3
  • 页码:238

您认为应该如何?

-最显著的区别编译器完成了……
+最显著的区别是编译器完成了……

图片
image

[勘误]反馈一个第12章第3节的错别字

问题描述
语句不通顺

如何找到这个错误

  • 章节:12.3.2-3
  • 页码:324

您认为应该如何?
可能的意思

-如果没有使用 go get 在执行之前下载依赖
+如果之前没有执行 go get 下载依赖

图片
image


如何找到这个错误

  • 章节:12.3.3-2-1
  • 页码:327

您认为应该如何?

-执行go get或go build命令时会就再次分析依赖情况
+执行go get或go build命令时会再次分析依赖情况

图片
image

[勘误]反馈一个第5章第3节的WaitGroup问题

问题描述
go1.16.6
Add()操作必须早于Wait(),否则会触发panic

如何找到这个错误

  • 章节:5
  • 页码:120

您认为应该如何?
go1.16.6版本,Wait早于Add()现在也不会panic了
不知道是不是golang版本的因素

代码

func main() {
	var wg sync.WaitGroup
	wg.Wait() //Wait早于Add()现在也不会panic了
	wg.Add(2) //设置计数器,数值即为goroutine的个数
	go func() {
		time.Sleep(1 * time.Second)

		fmt.Println("Goroutine 1 finished!")
		wg.Done() //goroutine执行结束后将计数器减1
	}()

	go func() {
		time.Sleep(2 * time.Second)

		fmt.Println("Goroutine 2 finished!")
		wg.Done() //goroutine执行结束后将计数器减1
	}()

	wg.Wait() //主goroutine阻塞等待计数器变为0
	fmt.Printf("All Goroutine finished!")
}

本书中可能可以改进的地方

收集了一些可能可以改进的地方,但会过多关注于细节,也可能说的不对,所以本issue仅供参考。

1.1.2节-3

第5页

 协程读取管道时,阻塞的条件有:
-管道无缓冲区;
+管道无缓冲区,且不存在阻塞等待写入的协程;
协程写入管道时,阻塞的条件有:
-管道无缓冲区;
+管道无缓冲区,且不存在阻塞等待读取的协程;

image

1.1.3节-2-3

第10页流程图

与“sendq非空==N”的后续条件保持一致

-有缓冲区?
+qcount>0?

image

2.2.3节-5

第83页

for-range迭代channel的伪代码,将变量名”index“改为”value“更合理。
image

4.1节-2

第102页

-(3)从mcache的alloc[class]链表中查询可用的span。
+(3)从mcache的alloc[class*2]或alloc[class*2+1]链表中查询可用的span。

image

5.2节-3

第120页

-Add()设置的值必须与实际等待的goroutine的个数一致,否则会触发panic。
+Add()设置的值必须与实际等待的goroutine的个数一致,否则会触发panic或导致死锁。

image

7.3.1节-2-22

第171页

common.sub

-子测试列表
+并发运行的子测试列表

image

8.1.2节-1

第211页

-任何实现了该方法的结构体都可以作为error来使用
+任何实现了该方法的数据类型都可以作为error来使用

image

8.1.4节-3

第225页

-类型断言替换成errors.As()时需要先声明一个目标类型的指针变量
+类型断言替换成errors.As()时需要先声明一个目标类型的变量,再传入该变量的指针

示例中*os.PathError实现了error接口,即os.PathError的指针类型实现了error接口,因此声明了该类型的变量,再取该变量的指针(即指针的指针)传入errors.As()
image

9.3.2节-1

-GOMAXPROCS的值不超过64的话,timersBucket桶的数量等于GOMAXPROCS。
+GOMAXPROCS的值不超过64的话,timersBucket桶的数量不会超过GOMAXPROCS。

timersBucket桶为按需创建。
image

第5章错别字

第5.3节-1-5-3

第133页

-注意:……,因为context是不支持cancle的
+注意:……,因为context是不支持cancel的

image

[勘误]第9章错别字

如何找到这个错误

  • 章节:9.3
  • 页码:276

您认为应该如何?

-保证定时器的按照约定的时间触发
+保证定时器按照约定的时间触发

图片
image


如何找到这个错误

  • 章节:9.3.1-1-2
  • 页码:278

您认为应该如何?

-sleeping...gp会投入睡眠
+sleeping...gp会进入睡眠

图片
image


如何找到这个错误

  • 章节:9.3.2-1-1
  • 页码:285

您认为应该如何?
插图

 timersBucket
-g
+gp
 t
 ...

图片
image


如何找到这个错误

  • 章节:9.3.2-1-2
  • 页码:285

您认为应该如何?
不太通顺,猜测可能的意思是

-timerproc实际上专门监控定时器的协程执行体
+timerproc实际是上专门监控定时器的协程

图片
image


如何找到这个错误

  • 章节:9.3.2-2-1
  • 页码:287

您认为应该如何?
猜测可能的意思是

-从Go 1.14起,处理器不再由timerproc处理
+从Go 1.14起,定时器不再由timerproc处理

图片
image

[第二版勘误]一些页面的问题

5页:“2)数据读写 ”一节中, 对 x, ok := <-ch 的论述

我个人觉得应该给出针对有缓冲区的管道、无缓冲区的管道的分开论述,毕竟无缓冲区的管道也可以进行 x, ok := <-ch。例如:

package main

import "fmt"

func main() {
	ch := make(chan int)

	go func() {
		ch <- 1
	}()

	x, ok := <-ch
	fmt.Printf("x=%v,ok=%v\n", x, ok) // x=1,ok=true
	close(ch)
	x, ok = <-ch
	fmt.Printf("x=%v,ok=%v\n", x, ok) // x=0,ok=false
}

这样才可以避免读者,在看到这一节的最后的一句“可以看到,只有管道已关闭且缓冲区中没有数据时,管道读取表达式返回的第二个变量才与管道关闭状态一致”时,误以为只有 “有缓冲区的”管道才可以这样操作,或认为“状态一致”只能在“有缓冲区的”管道中才会存在等。

[edit]

  • 2023.10.21(@RainbowMango): 很遗憾的是修订时不允许做大的修改,只允许字符级别的修订,这个意见接受,只能留待下版再考虑了。

7页:“

因读阻塞的协程会被向管道写入数据的协程唤醒。
因写阻塞的协程会被从管道读数据的协程唤醒。

个人觉得可以多一个字“取”,或少一个字“入”,这样看起对仗工整一点。

改后的效果:

因读阻塞的协程会被向管道写入数据的协程唤醒。
因写阻塞的协程会被从管道读取数据的协程唤醒。



因读阻塞的协程会被向管道写数据的协程唤醒。
因写阻塞的协程会被从管道读数据的协程唤醒。

[edit]

  • 2023.10.21(@RainbowMango): 确认可以把字删除,因为写数据协程唤醒阻塞的协程时,实际上数据还没写入。已修改

18~19页:capacity 、 length 与 长度、容量有点混合使用

根据前后文,个人建议都使用 长度、容量。

[edit]:

  • 2023.10.21(@RainbowMango): 使用capacitylength之处,上下文一般都有数据结构的描述,个人感觉使用英文单词更容易理解。如果我理解不对,还请指出具体修改点,感谢。

32页:第二段 ”而Go语言的map则在在负载因子达到6.5..."

多了一个“在”字,应该是”而Go语言的map则在负载因子达到6.5..."吧?

[edit]:

47页:“Name表示常量的名字,...”、“Value为常量值,与Name对应,...”

根据您在第46页中关于ValueSpec结构体的定义,这里的Name和Value应该修改成Names和Values吧?
若需要修改成Names和Values,则这两句可能需要修改成:
Names用于存储常量的名字,使用切片表示单行语句中声明的多个常量。
Values用于存储常量的值,与Names对应,表示常量的初始值。

[edit]:

diff --git a/chapter01/5.3-iota_principle.md b/chapter01/5.3-iota_principle.md
index c04b328..2de63d0 100644
--- a/chapter01/5.3-iota_principle.md
+++ b/chapter01/5.3-iota_principle.md
@@ -29,9 +29,9 @@ const (
 上面的常量声明块中仅包括一行声明语句,该语句对应一个`ValueSpec`结构。

 - Doc 表示块注释,往往会出现在文档中的注释;
-- Name 表示常量的名字,使用切片表示单行语句中声明的多个常量;
-- Type 常量类型;
-- Value 常量值,与Name对应,表示常量的初始值;
+- Names 表示常量的名字,使用切片表示单行语句中声明的多个常量;
+- Type 表示常量类型;
+- Values 表示常量值,与Name对应,表示常量的初始值;
 - Comment 表示行注释

47页:“Type为量类型”

少了一个“常”字,应该是“Type为常量类型”吧?

[edit]:

51页:“在使用for-range遍历字符串时,每次迭代将返回字符UTF-8编码的首个字节下标及字节值,...”

这里的“字节值”,需要修改成“字符值”。

[edit]:

  • 2023.10.21(@RainbowMango): 接受,已修改,同时也稍改了该句描述。
diff --git a/chapter01/6.2-string_usecase.md b/chapter01/6.2-string_usecase.md
index 7bd4422..5b9316a 100644
--- a/chapter01/6.2-string_usecase.md
+++ b/chapter01/6.2-string_usecase.md
@@ -88,7 +88,7 @@ func StringToByte() {
 #### 2.1 UTF编码
 string使用8比特字节的集合来存储字符,而且存储的是字符的UTF-8编码,例如每个汉字字符的UTF-8编码将占用多个字节。

-在使用for-range遍历字符串时,每次迭代将返回字符UTF-8编码的首个字节下标及字节值,这意味着下标可能不连续。
+在使用for-range遍历字符串时,每次迭代将返回字符的UTF-8编码首个字节下标及字符值,这意味着下标可能不连续。^M
 比如下面的函数:

51页:“字符串不支持取地址操作,也就无法修改字符串的值,...”

我想您要表达的是:对一个字符串的元素进行取地址操作。(ps: 这里的元素一说,我是看了go语言规范String types一节中的“It is illegal to take the address of such an element; if s[i] is the i'th byte of a string, &s[i] is invalid.”)。所以我觉得这里是有一点问题。字符串是可以进行取地址操作,例如:

package main

import "fmt"

func main() {
	s := "你好世界!你好**"
	fmt.Printf("%p\n", &s)

	s1 := s[0]
	fmt.Printf("%p\n", &s1)

	// fmt.Printf("%p\n", &s[0]) // 编译报错:invalid operation: cannot take address of s[0] (value of type byte)
}

[edit]:

diff --git a/chapter01/6.2-string_usecase.md b/chapter01/6.2-string_usecase.md
index 5b9316a..d090b06 100644
--- a/chapter01/6.2-string_usecase.md
+++ b/chapter01/6.2-string_usecase.md
@@ -115,7 +115,7 @@ s := "Hello"
 &s[0] = byte(104) // 非法
 s = "hello" // 合法
-字符串不支持取地址操作,也就无法修改字符串值,上面的语句中会有编译错误:
+字符串元素不支持取地址操作,也就无法修改字符串值,上面的语句中会有编译错误:

56页:“string也可以方便地转成byte切片示:”

这里多了一个“示”字。

[edit]:

  • 2023.10.21(@RainbowMango): 这里可能是编辑老师手误,书稿没问题,我会同步给出版社,感谢。

58页:编译器会识别如下临时场景的第二条:字符串拼接,如"<" + "string(b)" + ">"

这里我想不用在string(b)的前后加上双引号。

[edit]:

60页:题目三 选项C “sync.Map可以存储不同类型的键值对,这是它相对于原生map在灵活性方面的优势。”

选项C看起来也是对的。若是对的,则题目三应该是一个多选题。

[edit]:

  • 2023.10.21(@RainbowMango): 实际上存储不同类型不是优势,而是陷阱。

60页:最后一段 “sync.Map的数据结构中包含了锁,所以它不同在函数间传递”

其中的“它不同”应该是“它不能”吧?

[edit]:

62页:使用要点的第一点:“1)特定场景下性能够提升”

这句看起好像少了一个“能”,但多一个“能”字看起来有点奇怪,我觉得可以把“够”字换成“可”字。

[edit]:

  • 2023.10.21(@RainbowMango): 已修改。特定场景下可提升性能

75页:“当select的多个case语句中的管道均阻塞时,整个select语句也会陷入阻塞(没有default语句的情况下),直到任意一个管道解除阻塞。”

根据您前文的描述,这里的“多个case语句中”,我觉得,应该要修改成“全部case语句中”,多个的意思是大于1个,但并不表示全部的意思。例如:

package main

import "fmt"

func SelectForChan(c1 chan int, c2 chan int, c3 chan int) {
	select {
	case d := <-c1:
		fmt.Printf("c1 received: %d\n", d)
	case c1 <- 1:
		fmt.Printf("c1 sent %d\n", 1)
	case d := <-c2:
		fmt.Printf("c2 received: %d\n", d)
	case c2 <- 2:
		fmt.Printf("c2 sent %d\n", 2)
	case d := <-c3:
		fmt.Printf("c3 received: %d\n", d)
	case c3 <- 3:
		fmt.Printf("c3 sent %d\n", 3)
	}
}

func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	ch3 := make(chan int, 1)

	SelectForChan(ch1, ch2, ch3)
}

[edit]:

84页:题目四的答案

您在第86页给出的答案是D(函数触发panic),但根据您第86页的描述似乎答案应该是C(函数打印hi后阻塞)

但这道题,我觉得,可能还跟怎么调用该函数有关。例如:

package main

import (
	"fmt"
	"time"
)

func RangeTimer() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("panic: ", r)
		}
	}()

	t := time.NewTimer(time.Second)

	for _ = range t.C {
		fmt.Println("hi")
	}
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("panic: ", r)
		}
	}()

	go RangeTimer()

	time.Sleep(20 * time.Second)
}

将会打印出“hi”, 同时没有发生panic

如果是以下方式调用(少了 在 RangeTimer 前面使用 go关键字):

package main

import (
	"fmt"
	"time"
)

func RangeTimer() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("panic: ", r)
		}
	}()

	t := time.NewTimer(time.Second)

	for _ = range t.C {
		fmt.Println("hi")
	}
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("panic: ", r)
		}
	}()

	RangeTimer()

	time.Sleep(20 * time.Second)
}

则会打印出“hi”,之后报错:fatal error: all goroutines are asleep - deadlock!

所以这里我也不知道最后的答案是哪一个了。

[edit]:

  • 2023.10.21(@RainbowMango): 这个答案为C。这个是单单从函数角度看的,如果整个程序都阻塞,运行时会panic。

86页:2.2.2节 第二段 “由于range可以给循环变量赋值,使其起来好像函数返回一样”

“使其起来好像”应该是少了一个“看”字,应该是“使其看起来好像”吧?

[edit]:

  • 2023.10.21(@RainbowMango): 又一个编辑错误, 待同步给编辑老师.

88页:“rune类型,它仅代表Unicode编码的1个字节:”

这里的表述好像有点问题,我看其他文章或博客,说rune表示的是一个Unicode码点或字符。

[edit]:

  • 2023.10.21(@RainbowMango): 已修改,谢谢。确实是字符。

103页:“编写过C语言程序的读者肯定知道malloc()方法...”

这里malloc()在C语言中应该是函数,面向对象的编程语言或类似面向对象的编程语言中才有“方法”,所以这里应该是需要将“方法“这两字修改成“函数”吧?
[edit]:

  • 2023.10.21(@RainbowMango): 已修改,谢谢。确实函数更严谨些。

129页:““坐等协程”可能会永远无法被唤醒而产生列锁,...”

这里“列锁”,应该需要修改成“死锁”吧?

[edit]:

131页:content.Backgroud

少了一个字母“n”,应该是content.Background

[edit]:

132页:“context包中定义了一个公用的emptCtx全局变量”

emptCtx少了一个字母“y”,应该是emptyCtx吧?
[edit]:

132页:“context包提供了四个方法创建不同类型的context,使用这四个方法时如果没有父context,则需要出入backgroud,即将backgroud作为其父节点”

其中的backgroud,应该都是少了一个字母“n”,应该是background吧?

[edit]:

133页:“struct cancelCtx、timerCtx、valueCtx都继承于Context...”

这里的“继承于”,与您在第36页提到的“Go语言的struct与其他编程语言的class有些类似可以定义字段和方法,但是不可以继承。”,有一些矛盾。我看了官方的的 FAQ-Why is there no type inheritance?,以及 FAQ-Why doesn't Go have "implements" declarations?,说法和您在第36页说的一致。所以我想第133页的“继承于”应该修改成“实现了”吧?

[edit]:

134页:“实际上,WithCancel()返回的第二个用于cancel context的方法正是此cancel()。”

我看了go1.11源码中的WithCancel:

func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
	c := newCancelCtx(parent)
	propagateCancel(parent, &c)
	return &c, func() { c.cancel(true, Canceled) }
}

go 1.20.6的源码中的WithCancel:

func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
	c := withCancel(parent)
	return c, func() { c.cancel(true, Canceled, nil) }
}

感觉这句话好像有点问题,我个人觉得可以修改成:“实际上,WithCancel()返回的第二个值的匿名函数中用于cancel context的方法正是此cancel()。”

[edit]:

  • 2023.10.21(@RainbowMango): 这个暂时不改吧,没想到如何更简洁的表达。

135页:“返回cancelCtx实例和cancel方法。”

若134页改成使用到“匿名函数”,似乎这里就需要修改成“返回cancelCtx实例和cancel匿名函数。”

141页:“这里有一个细节需要关注,即当前context查找不到key时,会向父节点查找,如果查询不到则最终返回interface{}。”

“最后返回interface{}”,我看了go1.20.6的源码,其返回的是nil。不知道这里的interface{},是不是应该写成nil?

[edit]:

  • 2023.10.21(@RainbowMango): 这个暂时不改吧。context花费了10页篇幅,感觉过于繁琐,期望下一版能优化掉。

147页 “协程调度机制中的Process数量要大于1”

我看了您在97页中标注的是“P(processor):处理器...”,而这里写的是“Process”,我想应该是“Processor”吧?

[edit]:

156页:“题目一:如何判断Foo结构体中的两个变量是否相等?...” 和 “题目二:如何判断空接口类型中的两个变量是否相等?”

我个人感觉,这两句话读起来有点奇怪的感觉(句子表达中含有集合的概念)。我觉得可以修改成:

“题目一:如何判断两个Foo结构体变量是否相等?...” 和 “题目二:如何判断两个空接口类型变量是否相等?”

[edit]:

165页:“测试函数命名规则为TestXxx,其中Test为单元测试的固定开头,go test只会执行以此开头的方法。”

这句的后面部分“go test只会执行以此开头的方法”表述有点不对,和您在171页中的写到的“执行测试可以使用go test,此时该目录下的其他测试文件也会一并执行。”有点矛盾了。

还有一点,就是这句以“测试函数”开始、以“方法”结束,好像说的都是同一个事物,是否应该统一一下说法。

可以直接去除掉“只会”中的“只”,将方法修改为“测试函数”,修改后的效果:
“测试函数命名规则为TestXxx,其中Test为单元测试的固定开头,go test会执行以此开头的测试函数。”

[edit]:

166页 最底下的代码中的第一个注释 “//MakeSliceWithPreAlloc,不预分配内存”

应该需要修改为“//MakeSliceWithoutAlloc,不预分配内存”吧?

[edit]:

170~171页:页面中的"OutPut"中P大写的问题

目前我只在Windows系统上进行测试,OutPut中的P大写,是不影响示例测试的,但不知道在Linux中的是否会出现问题。
根据pkg testing 的说明给出的是:"Output: " 和 "Unordered output:"。

[edit]:

  • 2023.10.21(@RainbowMango): 已修改,谢谢。源码仓库里跑过CI,没问题,但为了严谨,还是改成Output

215页 “使用命令go get golang.org/x/pref/cmd/benchstat即可快捷安装benchstat...”

从 Go 1.16 开始,go install 是推荐用于构建和安装程序的命令。
-d 标志告诉 go get 不要构建或安装包。当使用 -d 时,go get 将只管理 go.mod 中的依赖项。
在没有-d的情况下使用go get来构建和安装包已经被废弃了(从Go 1.17开始)。
在 Go 1.18 中,-d 将永远被启用。

所以这里建议标注下不同版本的安装方式。go 1.16 是2021年2月16日发布的。
对于大于等于 go 1.16,应该建议使用以下方式安装:

go install golang.org/x/pref/cmd/benchstat@latest

[edit]:

  • 2023.10.21(@RainbowMango): 已修改,谢谢。同时 pref 应该为 perf。这里直接修改为 install了。不想维护老版本的用法了,随时间推移,旧版本没必要再记了。

219页 题目二 “答案为B和D”

这道题根据您下面的描述,应该也是为了说“答案为B和C”的!

以下运行后的结果

package main

import (
	"errors"
	"fmt"
)

func main() {
	err := errors.New("not found")
	err1 := fmt.Errorf("some context: %v", err)
	err2 := fmt.Errorf("some context: %w", err)

	fmt.Printf("err1的类型:%T\n", err1)
	fmt.Printf("err1的类型:%T\n", err2)

	fmt.Println(err1.Error())
	fmt.Println(err2.Error())

	if err1.Error() == err2.Error() {
		fmt.Println("eq")
	} else {
		fmt.Println("neq")
	}
}
// Output:
//err1的类型:*errors.errorString
//err1的类型:*fmt.wrapError
//some context: not found
//some context: not found
//eq

所以这道选择题最终的答案应该是“B和C”吧?

[edit]:

253页:“触发panic函数中的defer语句是否会执行”

是否应该在panic后加一个“后”字,应该是“触发panic后函数中的defer语句是否会执行”吧?

[edit]:

280页: 第二个代码块用于演示公交车发车场景的代码

应该是少了在 ticker := time.NewTicker(5 * time.Minute) 之后一行加上 defer ticker.Stop() 吧?

[edit]:

  • 2023.10.21(@RainbowMango): 您说得对,应该加个defer更严谨,此处由于函数不会退出,所以也不至于泄露。

303页:“然而,虽然应用很广泛,但并代表大家对它有深刻的认识”

这里,我猜测,是需要在“但并”后面加上一个“不”字,应该是“然而,虽然应用很广泛,但并不代表大家对它有深刻的认识”

[edit]:

314页:“大多数情况下,Go编译器根据传递的参数可以自动推导出类型”

虽然有些博客,或文章,弱化了形参和实参的称法,但我个人觉得还是有必要区分下。故这里我觉得应该是“大多数情况下,Go编译器根据传递的实参可以自动推导出类型”吧?

[edit]:

349页:第一段 “例如,要引用module module github.com/rehongcai/indirect中的内容时,其import路径需要为import github.com/renhongcai/indirect”

多了一个加粗显示的"module",以及少了在import 后面的一对双引号,应该是“例如,要引用 module github.com/rehongcai/indirect中的内容时,其import路径需要为import "github.com/renhongcai/indirect" ” 吧?

[edit]:

358页:中间部分 “go.mod只需记录直接依赖的依赖包版本,只在依赖包版本不包含go.mod文件时才会记录间接依赖包版本,...”

根据您在345页的表述,这里应该还少了345页描述中的第二种情况吧?所以我在想是不是可以在“只在依赖包版本不包含”后加上“在其”两个字,完整的表述是“go.mod只需记录直接依赖的依赖包版本,只在依赖包版本不包含在其go.mod文件时才会记录间接依赖包版本,...” ?

[edit]:

  • 2023.10.21(@RainbowMango): 这个暂时不改吧,事实上go.mod go.sum文件在最近的几个版本里还是有微调的,这个留待下一版再一并优化吧。

目前,我只读到 358页 ,后续阅读遇到问题再来请教下您。

不好意思,没按照您要求的格式给您的第二版书提出勘误,望见谅!

第1章错别字和笔误

1.2.2节-1-4

第17页

-切取的长度为 hight - low
+切取的长度为 high - low

1.3.3节-5-2

第36页

-如果当前map处理搬迁过程中
+如果当前map处于搬迁过程中

1.6.2节-1-4

第51页

-string转[]byte
-func StringToByte() {
+[]byte转string
+func ByteToString() {
    ...
}
-[]byte转string
-func ByteToString() {
+string转[]byte
+func StringToByte() {
    ...
}

[勘误]反馈一个第1章第1.2.1节的习题三

问题描述
执行结果是false

如何找到这个错误

  • 章节:第一章 1.2.1节
  • 页码:14-15

您认为应该如何?
package main

import "fmt"

func SliceExtend() {
var slice []int
s1 := append(slice, 1, 2, 3)
s2 := append(s1, 4)
fmt.Println(&s1[0] == &s2[0])
fmt.Println(&s1[0], &s2[0])
}

func main() {
SliceExtend()
}
结果应该是false

[勘误]反馈一个第7章7.1.3的测试命令问题

问题描述
go test example_test.go 执行报错:
.\example_test.go:12:2: undefined: SayHello
.\example_test.go:17:2: undefined: SayGoodbye
.\example_test.go:24:2: undefined: PrintNames
FAIL command-line-arguments [build failed]

如何找到这个错误

  • 章节:第7章
  • 页码:161页

您认为应该如何?
应该改成:
go test example_test.go example.go
图片
如果有可能,尽量提供图片。
Snipaste_2022-03-17_22-41-02

其他补充信息

[勘误]反馈一个第11章第5节的错别字

问题描述
A clear and concise description of what the bug is.

如何找到这个错误

  • 章节:11.5.2-3
  • 页码:

您认为应该如何?

-并将可执行文件目录添加到GOPATH中
+-并将可执行文件目录添加到PATH中

图片
image

关于1.6.3节string的疑问

编译优化小节说临时将[]byte转为string的场景,编译器会优化为直接把string.str指向[]byte的底层数据,避免复制。这样会不会引起并发问题,如果有另一个协程正在操作这个[]byte会有问题吗?

[第2版勘误]反馈一个第1章第1.3.2节的错别字

问题描述
27页倒数第三行错别字

如何找到这个错误

  • 章节:1.3.2
  • 页码:27

您认为应该如何?
早查询操作中 应为
在查询操作中

图片
如果有可能,尽量提供图片。
1

其他补充信息

[勘误]反馈一个第1章第1.2.2节的错别字

问题描述
声明和初始化切片的方式主要有几下几种:

如何找到这个错误

  • 章节:1.2.2
  • 页码:16

您认为应该如何?
声明和初始化切片的方式主要有以下几种:

图片
golang

第4章错别字和笔误

4.1节-1

第95页

插图中的bitmap

-512GB
+16GB

4.1节-1-1

第95页

-会将span中的一页会划分为更小的粒度
+会将span中的一页划分为更小的粒度

4.1节-1-1-1

第97页

-即 (bytes/spans) / (bytes/obj)
+即 (bytes/span) / (bytes/obj)
-即 (bytes/spans) % (bytes/obj)
+即 (bytes/span) % (bytes/obj)

4.1节-1-1-2

第98页

插图中的spans

-521MB
+512MB

[勘误]反馈一个第五章第三节的内容错误

问题描述
书中的描述和对应代码貌似不一致

如何找到这个错误

  • 章节:第五章第三节(context-> timerCtx)
  • 页码:130页

您认为应该如何?
代码中写的是 5 * time.Second 应该对应5秒,而书上写的是十秒。

图片
go-book-bug

关于1.2.3节slice扩容的特殊情况

除了常规的按现有容量×2或×1.25倍,有个特殊情况是如果append新加入的元素超过了按倍数扩容的容量,其实际扩容容量会满足append的需求,经过测试貌似是实际需求容量向上取偶数,测试代码如下:

s:=[]int{1,2,3,4,5,6,7,8}
fmt.Println(len(s),cap(s))      // 8 8

s1:=append(s,9,10,11,12,13,14,15,16)
fmt.Println(len(s1),cap(s1))    // 16 16

s2:=append(s,9,10,11,12,13,14,15,16,17)
fmt.Println(len(s2),cap(s2))    // 17 18

s3:=append(s,9,10,11,12,13,14,15,16,17,18)
fmt.Println(len(s3),cap(s3))    // 18 18

s4:=append(s,9,10,11,12,13,14,15,16,17,18,19)
fmt.Println(len(s4),cap(s4))    // 19 20

s5:=append(s,9,10,11,12,13,14,15,16,17,18,19,20)
fmt.Println(len(s5),cap(s5))    // 20 20

s6:=append(s,9,10,11,12,13,14,16,16,17,18,19,20,21)
fmt.Println(len(s6),cap(s6))    // 21 22

s7:=append(s,9,10,11,12,13,14,17,17,17,18,19,20,21,22)
fmt.Println(len(s7),cap(s7))    // 22 22

[勘误]反馈一个第8章第3节的错别字

问题描述
错别字

如何找到这个错误

  • 章节:8.3.2-2
  • 页码:246

您认为应该如何?

-程序将立即中止当前defer函数的执行
+程序将立即终止当前defer函数的执行
-那么panic的处理流程就会中止
+那么panic的处理流程就会终止

图片
image

其他补充信息

[勘误]反馈一个第8章第2节的错别字

问题描述
defer的执行:取出defer->_defer

如何找到这个错误

  • 章节:8.2.3-2
  • 页码:236

您认为应该如何?

-deferreturn():用于将defer从goroutine链表中取出并执行
+deferreturn():用于将_defer从goroutine链表中取出并执行

图片
image

其他补充信息

[勘误]反馈一个第1章第1.2节slice的勘误

问题描述
p14 题目三

func SliceExtend() {
  var slice []int
  s1 := append(slice, 1, 2, 3)
  s2 := append(s1, 4)
  fmt.Println(&s1[0] == &s2[0])
}

参考答案

true

如何找到这个错误

  • 章节:1.2
  • 页码:14

您认为应该如何?
应该输出false(实际也是)。

图片

其他补充信息

【第二版】for-range热身测验-题目二

问题描述

// 题目二: 引用循环变量下标
func PrintSlice() {
	s := []int{1, 2, 3}
	var wg sync.WaitGroup
	wg.Add(len(s))
	for _, v := range s {
		go func() {
			fmt.Println(v)
			wg.Done()
		}()
	}
	wg.Wait()
}

// Output并不是 3, 3, 3,三个协程会从数组中随机执行

如何找到这个错误

  • 章节:第二章
  • 页码:P85

您认为应该如何?
=== RUN TestPrintSlice
3
2
1
--- PASS: TestPrintSlice (0.00s)

图片
如果有可能,尽量提供图片。

其他补充信息

[勘误]反馈一个第2章第2节的错别字,2.2.1,77页

问题描述
2.2.1,77页
题目四,“答案为D ” 。这个是错的。应该为:“ 答案为C”

如何找到这个错误

  • 章节:
  • 页码:

您认为应该如何?

图片
如果有可能,尽量提供图片。

其他补充信息
我写了代码进行测试:
package main

import (
"fmt"
"time"
)

func main() {
RangeTimer()
}

func RangeTimer() {
t := time.NewTimer(time.Second)

for _ = range t.C {
	fmt.Println("hi")
}

}
输出:
hi
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.RangeTimer()
/Users//go/src/gitee.com/wide288/test/for-range1/main.go:15 +0xcc
main.main()
/Users/
/go/src/gitee.com/wide288/test/for-range1/main.go:9 +0x25

[勘误]反馈一个第8章第3节的错别字

问题描述
错别字

如何找到这个错误

  • 章节:8.3.3-2
  • 页码:247

您认为应该如何?

-标记录前panic是否被中断
+标记当前panic是否被中断

图片
image

其他补充信息

关于第4章GC部分的一些疑问

  1. GC在标记mspan中被引用的对象后产生的gcmarkBits,会作为新的allocBits,那么是否也应该同时更新allocCount
  2. GC在三色标记对象引用时,对象的引用应该是指向被分配的地址吧(也就是arena中的page中的某个位置)?但gcmarkBits是在mspan中,Go是如何通过对象地址反向找出对应mspan的?

关于5.3节context的想法

之前读到context的定义,其中嵌入了上级类型,例如cancelCtx 中的Context

type cancelCtx struct {
	Context
        ......
}

我一直以为仅仅是重用了上一级的接口定义,与parent之间的联系由私有成员变量维护,而实际是直接在嵌入类型中存放了parent实例,之前一直没留意到,书中也没重点提及,感觉可以加强一下。

77页 4) 题目四 答案应为C

题目和选项如此图
75 (2)

按77页的描述,应该在1s后打印字符串然后阻塞,符合75页选项C,不符合选项D
77

关于1.3.3节hmap的疑问

  1. 确定bucket的index:书上说是用hash的低位与hmap.B取模,是否应该是与2^hmap.B取模?
  2. 增量扩容:32页的图是否B=0更合理?33页的图是否B=1更合理?
  3. 如何确定bucket的某一项是空闲的,因为全0的值也可以是有效的tophash,key或者value?
  4. 完成扩容迁移:从oldbuckets迁移到buckets,项目应该是重新分布在各个bucket中的吧,而不应该还是集中在同一个bucket中?34页的图显示迁移过来的项目仍然集中在一个bucket中。

[勘误]反馈一个第8章第1节的错别字

问题描述
热身项目答案有误

如何找到这个错误

  • 章节:8.1.1-2-2
  • 页码:210

您认为应该如何?
题目二

-答案为B和D。
+答案为B和C。

图片
image
image

其他补充信息

[勘误]反馈一个第2章第2.1.1节的bug

问题描述
习题五
对下面的函数描述正确的是(单选)
func SelectExam5() {
select {}
}
答案是:C函数陷入阻塞
但是实际的执行结果是:A:编译错误,select语句非法

如何找到这个错误

  • 章节:2.1.1
  • 页码:62-63

您认为应该如何?

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select (no cases)]:
main.main()
应该是 A:编译错误,select语句非法

[勘误]反馈一个第8章第4节的错别字

问题描述
A clear and concise description of what the bug is.

如何找到这个错误

  • 章节:8.4.3-2-2
  • 页码:259

您认为应该如何?

-恢复无效,因为_panic.recovered = true
+恢复无效,因为_panic.recovered == true

图片
image

其他补充信息

第3章可能笔误的地方

3.1节-2

第87页

-协程调度器……及时把阻塞的协程调度出协程
+协程调度器……及时把阻塞的协程调度出线程

猜测可能是这个意思?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.