元数据
Go语言精进之路:从新手到高手的编程思想、方法和技巧2
- 书名: Go语言精进之路:从新手到高手的编程思想、方法和技巧2
- 作者: 白明
- 简介:
- 出版时间
- ISBN:
- 分类:
- 出版社: 机械工业出版社
高亮划线
40.2 包内测试与包外测试
-
📌 包内测试这种方法本质上是一种白盒测试方法。 ^CB-88q19I1CCFZc6aC6YE-11-1892-2014
- ⏱ 2022-07-25 23:40:12
-
📌 采用包内测试可能会遇到一个绕不过去的硬伤:包循环引用。 ^CB-88q19I1CCFZc6aC6YE-11-3291-3318
- ⏱ 2022-07-25 23:42:07
-
📌 包外测试的本质是一种面向接口的黑盒测试。 ^CB-88q19I1CCFZc6aC6YE-11-5748-5934
- ⏱ 2022-07-25 23:42:41
-
📌 export_test.go文件 ^CB-88q19I1CCFZc6aC6YE-11-7720-7736
- ⏱ 2022-07-25 23:45:45
-
📌 用于将被测包的内部符号在测试阶段暴露给包外测试代码 ^CB-88q19I1CCFZc6aC6YE-11-7799-7824
- ⏱ 2022-07-25 23:45:59
-
📌 图40-4 export_test.go为包外测试充当“后门” ^CB-88q19I1CCFZc6aC6YE-11-8780-8811
- ⏱ 2022-07-25 23:47:43
41.3 测试固件
- 📌 func setUp() func(){ … return func() { }}func TestXxx(t *testing.T) { t.Cleanup(setUp()) …} ^CB-88q19I1CCFZc6aC6YE-15-2884-3033
- ⏱ 2022-07-26 00:05:38
42.1 Go测试代码的一般逻辑
- 📌 对测试失败与否的判断在于测试代码逻辑是否进入了包含Error/Errorf、Fatal/Fatalf等方法调用的代码分支。一旦进入这些分支,即代表该测试失败。不同的是Error/Errorf并不会立刻终止当前goroutine的执行,还会继续执行该goroutine后续的测试,而Fatal/Fatalf则会立刻停止当前goroutine的测试执行。 ^CB-88q19I1CCFZc6aC6YE-17-447-622
- ⏱ 2022-07-26 00:07:33
42.2 表驱动的测试实践
- 📌 表驱动的测试 ^CB-88q19I1CCFZc6aC6YE-18-2543-2627
- ⏱ 2022-07-26 02:18:31
43.2 golden文件惯用法
- 📌 golden ^CB-88q19I1CCFZc6aC6YE-23-2759-2765
- ⏱ 2022-07-26 02:57:39
44.1 fake:真实组件或服务的简化实现版替身
-
📌 简化版实现 ^CB-88q19I1CCFZc6aC6YE-25-545-622
- ⏱ 2022-07-26 10:40:22
-
📌 可以基于哈希表实现一个内存版数据库 ^CB-88q19I1CCFZc6aC6YE-25-701-718
- ⏱ 2022-07-26 10:43:13
-
📌 :并不具备在测试前对返回结果进行预设置的能力 ^CB-88q19I1CCFZc6aC6YE-25-5587-5609
- ⏱ 2022-07-26 11:01:08
44.2 stub:对返回结果有一定预设控制能力的替身
-
📌 测试前对调用结果预设置 ^CB-88q19I1CCFZc6aC6YE-26-419-430
- ⏱ 2022-07-26 10:54:39
-
📌 gostub ^CB-88q19I1CCFZc6aC6YE-26-6487-6493
- ⏱ 2022-07-26 11:16:51
44.3 mock:专用于行为观察和验证的替身
-
📌 除了能提供测试前的预设置返回结果能力之外,还可以对mock替身对象在测试过程中的行为进行观察和验证 ^CB-88q19I1CCFZc6aC6YE-27-387-436
- ⏱ 2022-07-26 11:41:57
-
📌 gomock ^CB-88q19I1CCFZc6aC6YE-27-641-647
- ⏱ 2022-07-26 11:43:01
-
📌 通过代码生成的方式生成实现某接口的替身类型 ^CB-88q19I1CCFZc6aC6YE-27-1105-1126
- ⏱ 2022-07-26 11:44:25
第45条 使用模糊测试让潜在bug无处遁形
- 📌 模糊测试就是指半自动或自动地为程序提供非法的、非预期、随机的数据,并监控程序在这些输入数据下是否会出现崩溃、内置断言失败、内存泄露、安全漏洞等情况 ^CB-88q19I1CCFZc6aC6YE-28-1019-2041
- ⏱ 2022-07-26 13:35:33
45.3 go-fuzz使用方法
- 📌 采用遗传算法,不断基于corpus中的语料生成新的输入语料 ^CB-88q19I1CCFZc6aC6YE-31-3716-3745
- ⏱ 2022-07-26 13:57:21
45.5 让模糊测试成为“一等公民”
- 📌 模糊测试最适合那些处理复杂输入数据的程序 ^CB-88q19I1CCFZc6aC6YE-33-2219-2239
- ⏱ 2022-07-26 14:10:21
46.2 顺序执行和并行执行的性能基准测试
-
📌 并行执行的性能基准测试的代码写法如下 ^CB-88q19I1CCFZc6aC6YE-36-6724-6801
- ⏱ 2022-07-26 14:22:53
-
📌 顺序执行的性能基准测试其代码写法如下: ^CB-88q19I1CCFZc6aC6YE-36-842-887
- ⏱ 2022-07-26 14:23:09
-
📌 通过go test的命令行参数-benchtime将1秒这个默认性能基准测试函数执行时间改为2秒 ^CB-88q19I1CCFZc6aC6YE-36-4314-4362
- ⏱ 2022-07-26 14:23:55
-
📌 针对BenchmarkParalell基准测试的每一轮执行,go test都会启动GOMAXPROCS数量的新goroutine,这些goroutine共同执行b.N次循环,每个goroutine会尽量相对均衡地分担循环次数。 ^CB-88q19I1CCFZc6aC6YE-36-13240-13353
- ⏱ 2022-07-26 14:32:34
46.3 使用性能基准比较工具
-
📌 benchstat ^CB-88q19I1CCFZc6aC6YE-37-5299-5308
- ⏱ 2022-07-26 14:43:07
-
📌 p=0.008是一个用于衡量两个样本集合的均值是否有显著差异的指标。benchstat支持两种检验算法:一种是UTest(Mann Whitney UTest,曼-惠特尼U检验),UTest是默认的检验算法;另外一种是Welch T检验(TTest)。一般p值小于0.05的结果是可接受的。 ^CB-88q19I1CCFZc6aC6YE-37-5956-6101
- ⏱ 2022-07-26 14:48:18
47.1 pprof的工作原理
-
📌 导入net/http/pprof包即可 ^CB-88q19I1CCFZc6aC6YE-40-8408-8427
- ⏱ 2022-07-26 18:10:16
-
📌 命令行交互方式下最常用的命令是topN(N为数字,如果不指定,默认等于10) ^CB-88q19I1CCFZc6aC6YE-40-12971-13009
- ⏱ 2022-07-26 18:15:46
-
📌 倒置火焰图每个函数调用栈的最下方就是正在执行的函数,上方都是它的父函数。 ^CB-88q19I1CCFZc6aC6YE-40-20793-20829
- ⏱ 2022-07-26 18:26:24
48.1 expvar包的工作原理
- 📌 Go标准库中的expvar包提供了一种输出应用内部状态信息的标准化方案 ^CB-88q19I1CCFZc6aC6YE-43-354-503
- ⏱ 2022-07-26 19:22:11
48.2 自定义应用通过expvar输出的度量数据
-
📌 测量型 ^CB-88q19I1CCFZc6aC6YE-44-3467-3516
- ⏱ 2022-07-26 19:41:26
-
📌 我们在设计能反映Go应用内部状态的自定义指标时,经常会设计下面两类指标。 ^CB-88q19I1CCFZc6aC6YE-44-3337-3373
- ⏱ 2022-07-26 19:41:35
-
📌 计数型 ^CB-88q19I1CCFZc6aC6YE-44-3667-3716
- ⏱ 2022-07-26 19:41:42
49.3 Delve调试基础、原理与架构
-
📌 常用的查看命令如下。print(简写为p):输出源码中变量的值。whatis:输出后面的表达式的类型。regs:当前寄存器中的值。locals:当前函数栈本地变量列表(包括变量的值)。args:当前函数栈参数和返回值列表(包括参数和返回值的值)。examinemem(简写为x):查看某一内存地址上的值。 ^CB-88q19I1CCFZc6aC6YE-49-5550-5917
- ⏱ 2022-07-26 23:20:10
-
📌 Delve还支持在调试过程中修改变量的值,并手工调用函数 ^CB-88q19I1CCFZc6aC6YE-49-10066-10094
- ⏱ 2022-07-26 23:24:26
-
📌 (dlv) set a = 4 ^CB-88q19I1CCFZc6aC6YE-49-10540-10557
- ⏱ 2022-07-26 23:24:53
-
📌 (dlv) call foo.Foo(a, b) ^CB-88q19I1CCFZc6aC6YE-49-10571-10597
- ⏱ 2022-07-26 23:24:59
-
📌 通过stack命令(可简写为bt)可以输出函数调用栈信息 ^CB-88q19I1CCFZc6aC6YE-49-7992-8020
- ⏱ 2022-07-26 23:35:43
49.4 并发、Coredump文件与挂接进程调试
-
📌 通过Delve提供的goroutines命令来查看当前程序内的goroutine列表 ^CB-88q19I1CCFZc6aC6YE-50-3070-3112
- ⏱ 2022-07-26 23:34:07
-
📌 可以通过goroutine命令切换到其他goroutine中,比如切换到main goroutine(goroutine 1)中:(dlv) goroutine 1 ^CB-88q19I1CCFZc6aC6YE-50-5190-5294
- ⏱ 2022-07-26 23:36:43
-
📌 要想在Linux下让Go程序崩溃时产生core文件,我们需要进行一些设置(因为默认情况下Go程序崩溃并不会产生core文件):
go build main.go$GOTRACEBACK=crash ./main ^CB-88q19I1CCFZc6aC6YE-50-7527-7693 - ⏱ 2022-07-26 23:40:17
50.1 TCP Socket网络编程模型
-
📌 阻塞和非阻塞是以内核是否等数据全部就绪才返回(给发起系统调用的应用线程)来区分的。 ^CB-88q19I1CCFZc6aC6YE-53-1004-1045
- ⏱ 2022-07-27 01:28:48
-
📌 Go语言在netpoller中采用了I/O多路复用模型。 ^CB-88q19I1CCFZc6aC6YE-53-8235-8263
- ⏱ 2022-07-27 11:05:26
50.3 Socket读写
-
📌 在写入超时时,依旧存在数据部分写入的情况 ^CB-88q19I1CCFZc6aC6YE-55-13464-13611
- ⏱ 2022-07-27 14:21:31
-
📌 没出现读出部分数据且返回超时错误的情况 ^CB-88q19I1CCFZc6aC6YE-55-8393-8412
- ⏱ 2022-07-27 14:22:04
50.5 关闭连接
- 📌 从client1的运行结果来看,在己方已经关闭的Socket上再进行Read和Write操作,会得到“use of closed network connection”的错误。而从server1的执行结果来看,在对方关闭的Socket上执行Read操作会得到EOF错误,但Write操作依然会成功,因为数据会成功写入己方的内核Socket缓冲区中,即便最终发不到对方的Socket缓冲区(因为己方Socket尚未关闭)。因此当发现对方Socket关闭时,己方应该正确处理自己的Socket,再继续进行Write操作已经无任何意义了。 ^CB-88q19I1CCFZc6aC6YE-57-2366-2632
- ⏱ 2022-07-27 14:54:28
51.3 非对称加密和公钥证书
-
📌 一般浏览器或操作系统在出厂时就内置了诸多知名CA(如Verisign、GoDaddy、CNNIC等)的公钥数字证书,这些CA的公钥证书可以用于验证这些CA机构为网站颁发的公钥证书。 ^CB-88q19I1CCFZc6aC6YE-61-2895-2985
- ⏱ 2022-07-27 16:58:08
-
📌 来自签发机构的签名 ^CB-88q19I1CCFZc6aC6YE-61-3601-3610
- ⏱ 2022-07-28 14:11:05
51.5 对客户端公钥证书的校验
- 📌 数字证书就是使用CA私钥对证书申请者的公钥和证书相关信息进行签名后的满足标准证书格式的信息 ^CB-88q19I1CCFZc6aC6YE-63-4557-4602
- ⏱ 2022-07-28 14:43:05
52.1 字符与字符集
- 📌 每个字符都有两个属性:码点(codepoint)和表示这个码点的内存编码 ^CB-88q19I1CCFZc6aC6YE-65-4049-4473
- ⏱ 2022-07-28 14:50:50
52.2 Unicode字符集的诞生与UTF-8编码方案
- 📌 如果没有提供字节序标记,则默认采用大端字节序解码。 ^CB-88q19I1CCFZc6aC6YE-66-5282-5307
- ⏱ 2022-07-28 15:04:29
52.3 字符编码方案间的转换
-
📌 golang.org/x/text ^CB-88q19I1CCFZc6aC6YE-67-4059-4076
- ⏱ 2022-07-28 15:16:27
-
📌 利用transform.Reader链实现任意字符编码间的转换 ^CB-88q19I1CCFZc6aC6YE-67-9396-9427
- ⏱ 2022-07-28 15:23:37
53.1 时间的基础操作
-
📌 连续两次通过Now函数获取的挂钟时间之间的差值不一定都是正值。 ^CB-88q19I1CCFZc6aC6YE-69-2350-2381
- ⏱ 2022-07-28 16:35:43
-
📌 单调时间表示的是程序进程启动之后流逝的时间 ^CB-88q19I1CCFZc6aC6YE-69-2502-2637
- ⏱ 2022-07-28 16:37:33
-
📌 图53-1 当hasMonotonic为1时,time.Time表示时间的原理 ^CB-88q19I1CCFZc6aC6YE-69-3659-3698
- ⏱ 2022-07-28 16:50:44
-
📌 距1885年1月1日的秒数 ^CB-88q19I1CCFZc6aC6YE-69-3966-3979
- ⏱ 2022-07-28 16:51:02
-
📌 图53-2 当hasMonotonic为0时,time.Time表示时间的原理 ^CB-88q19I1CCFZc6aC6YE-69-4837-4876
- ⏱ 2022-07-28 16:51:21
-
📌 距公元元年1月1日的秒数 ^CB-88q19I1CCFZc6aC6YE-69-5116-5128
- ⏱ 2022-07-28 16:52:56
53.2 时间的格式化输出
- 📌 参考时间(reference time) ^CB-88q19I1CCFZc6aC6YE-70-2183-2457
- ⏱ 2022-07-29 11:03:01
53.3 定时器的使用
-
📌 为每个P分配的定时器最小堆 ^CB-88q19I1CCFZc6aC6YE-71-2868-3008
- ⏱ 2022-07-29 11:33:53
-
📌 我们看到sendTime还加了双保险:通过一个select判断channel c的缓冲区是否已满,一旦满了,则会执行default分支而直接退出。 ^CB-88q19I1CCFZc6aC6YE-71-3801-3874
- ⏱ 2022-07-29 11:38:11
-
📌 f的执行并不在锁内 ^CB-88q19I1CCFZc6aC6YE-71-11253-11262
- ⏱ 2022-07-29 13:39:35
54.1 为什么不能忽略对系统信号的处理
- 📌 对于中断键触发的SIGINT信号,系统的默认处理动作是终止该应用进程 ^CB-88q19I1CCFZc6aC6YE-73-1679-1713
- ⏱ 2022-07-29 16:09:07
54.2 Go语言对系统信号处理的支持
-
📌 func Notify(c chan<- os.Signal, sig …os.Signal) ^CB-88q19I1CCFZc6aC6YE-74-2634-2707
- ⏱ 2022-07-29 16:35:26
-
📌 用来设置捕捉那些应用关注的系统信号 ^CB-88q19I1CCFZc6aC6YE-74-2710-2727
- ⏱ 2022-07-29 16:35:45
-
📌 同步信号之外的信号都被Go划归为异步信号。 ^CB-88q19I1CCFZc6aC6YE-74-3769-3790
- ⏱ 2022-07-29 16:42:26
-
📌 Notify无法捕捉SIGKILL和SIGSTOP(操作系统机制决定的),也无法捕捉同步信号(Go运行时决定的),只有捕捉异步信号才是有意义的。 ^CB-88q19I1CCFZc6aC6YE-74-4099-4171
- ⏱ 2022-07-29 16:44:47
-
📌 如果多次调用Notify拦截某信号,但每次调用使用的channel不同,那么当应用进程收到异步信号时,Go运行时会给每个channel发送一份异步信号副本 ^CB-88q19I1CCFZc6aC6YE-74-5510-5587
- ⏱ 2022-07-29 16:51:21
-
📌 在使用Notify函数时,要根据业务场景的要求,适当选择channel缓冲区的大小。 ^CB-88q19I1CCFZc6aC6YE-74-8197-8239
- ⏱ 2022-07-29 16:57:33
-
📌 在同一个channel上两次调用Notify函数 ^CB-88q19I1CCFZc6aC6YE-74-6351-6375
- ⏱ 2022-07-29 16:58:44
-
📌 channel仅收到一个信号 ^CB-88q19I1CCFZc6aC6YE-74-6934-6948
- ⏱ 2022-07-29 16:58:55
-
📌 同步信号是指那些由程序执行错误引发的信号,包括SIGBUS(总线错误/硬件异常)、SIGFPE(算术异常)和SIGSEGV(段错误/无效内存引用)。 ^CB-88q19I1CCFZc6aC6YE-74-3484-3558
- ⏱ 2022-07-29 16:59:38
54.3 使用系统信号实现程序的优雅退出
- 📌 等待处于活动状态的连接处理完毕 ^CB-88q19I1CCFZc6aC6YE-75-2702-2717
- ⏱ 2022-08-01 09:46:36
55.1 Go密码学包概览与设计原则
- 📌 aes包:实现了对称密码标准中的Advanced Encryption Standard(AES,亦称Rijndael算法)。 ^CB-88q19I1CCFZc6aC6YE-77-1470-1533
- ⏱ 2022-08-01 10:40:36
55.2 分组密码算法
-
📌 密码算法可以分为分组密码(block cipher)和流密码(stream cipher)两种。 ^CB-88q19I1CCFZc6aC6YE-78-348-396
- ⏱ 2022-08-01 10:12:30
-
📌 AES ^CB-88q19I1CCFZc6aC6YE-78-7128-7131
- ⏱ 2022-08-01 10:39:43
-
📌 是对称密码算法的首选 ^CB-88q19I1CCFZc6aC6YE-78-7179-7189
- ⏱ 2022-08-01 10:39:51
55.3 公钥密码
-
📌 RSA是世界上使用最广泛的公钥密码算法 ^CB-88q19I1CCFZc6aC6YE-79-1646-1665
- ⏱ 2022-08-01 11:02:33
-
📌 RSA-OAEP(Optimal Asymmetric Encryption Padding,最优非对称加密填充)则被认为是一种可信赖、满足强度要求的填充方案 ^CB-88q19I1CCFZc6aC6YE-79-3444-3523
- ⏱ 2022-08-01 11:09:59
-
📌 RSA算法对待处理的数据长度是有要求的,采用RSA-OAEP填充时,加密函数EncryptOAEP支持的最大明文长度为RSA密钥长度(字节数)-单向散列结果长度×2-2。 ^CB-88q19I1CCFZc6aC6YE-79-5318-5403
- ⏱ 2022-08-01 11:14:27
-
📌 随机数生成器 ^CB-88q19I1CCFZc6aC6YE-79-4420-4426
- ⏱ 2022-08-01 11:16:21
-
📌 随机数生成器的种子 ^CB-88q19I1CCFZc6aC6YE-79-4544-4553
- ⏱ 2022-08-01 11:16:30
55.4 单向散列函数
-
📌 单向散列函数(one-way hash function)是一个接受不定长输入但产生定长输出的函数,这个定长输出被称为“摘要”(digest)或“指纹”(fingerprint)。 ^CB-88q19I1CCFZc6aC6YE-80-377-1070
- ⏱ 2022-08-01 11:14:04
-
📌 SHA-256是这个标准中使用最多的单向散列函数 ^CB-88q19I1CCFZc6aC6YE-80-2994-3018
- ⏱ 2022-08-01 11:24:23
55.5 消息认证码
-
📌 消息认证码是一种不仅能确认数据完整性,还能保证消息来自期望来源的密码技术。消息认证码技术是以通信双方共享密钥为前提的。 ^CB-88q19I1CCFZc6aC6YE-81-1279-1338
- ⏱ 2022-08-01 11:37:47
-
📌 hmac的使用与单向散列函数类似,只是多了一个密钥而已 ^CB-88q19I1CCFZc6aC6YE-81-3161-3188
- ⏱ 2022-08-01 11:45:25
-
📌 crypto/hmac包就是一种基于单向散列函数的消息认证码实现 ^CB-88q19I1CCFZc6aC6YE-81-2368-2400
- ⏱ 2022-08-01 11:51:09
55.6 数字签名
-
📌 单凭消息认证码无法防止否认(non-repudiation) ^CB-88q19I1CCFZc6aC6YE-82-567-698
- ⏱ 2022-08-01 11:53:07
-
📌 通常对消息的摘要进行签名 ^CB-88q19I1CCFZc6aC6YE-82-3406-3418
- ⏱ 2022-08-01 15:24:20
-
📌 RSA-PSS算法通过采用对消息摘要进行签名,并在计算散列值时对消息加盐(salt)的方式来提高安全性 ^CB-88q19I1CCFZc6aC6YE-82-3872-3923
- ⏱ 2022-08-01 17:09:59
-
📌 数字证书本质上就是将公钥当作消息,由一个可信的第三方证书签发授权组织(CA)使用私钥对其进行签名。公钥内容和签名共同构成了数字证书。 ^CB-88q19I1CCFZc6aC6YE-82-5684-5750
- ⏱ 2022-08-01 17:17:23
55.7 随机数生成
-
📌 随机数源/dev/urandom ^CB-88q19I1CCFZc6aC6YE-83-595-611
- ⏱ 2022-08-01 17:31:15
-
📌 如果我们自己要使用随机数,可以使用rand.Read函数,该函数本质上是对rand.Reader的浅封装 ^CB-88q19I1CCFZc6aC6YE-83-940-992
- ⏱ 2022-08-01 17:34:03
-
📌 对称密码(分组密码):解决数据机密性的问题。公钥密码:解决密钥分发的问题。单向散列函数:解决消息完整性检查问题。消息认证码:可以识别伪装者。数字签名:解决消息究竟是谁所发的问题,防止否认。 ^CB-88q19I1CCFZc6aC6YE-83-1787-2001
- ⏱ 2022-08-01 17:36:12
56.6 快速对接I/O模型
- 📌 strings和bytes包提供了快速创建满足io.Reader接口的方案。利用这两个包的NewReader函数并传入我们的数据域即可创建一个满足io.Reader接口的实例 ^CB-88q19I1CCFZc6aC6YE-90-1084-1171
- ⏱ 2022-08-02 19:16:05
57.2 直接读写抽象数据类型实例
- 📌 gob包支持对任意抽象数据类型实例的直接读写 ^CB-88q19I1CCFZc6aC6YE-93-6961-6983
- ⏱ 2022-08-02 20:10:44
58.1 简洁的unsafe包
-
📌 ArbitraryType并不真正属于unsafe包,我们在Go代码中并不能使用ArbitraryType来定义变量,它表示一个任意表达式的类型,仅用于文档目的,Go编译器会对其做特殊处理。 ^CB-88q19I1CCFZc6aC6YE-96-697-792
- ⏱ 2022-08-02 23:42:37
-
📌 变量的地址必须可被该变量的对齐系数整除。 ^CB-88q19I1CCFZc6aC6YE-96-2108-2382
- ⏱ 2022-08-03 00:02:42
-
📌 Alignof函数就是用来获取传入表达式的对齐系数的 ^CB-88q19I1CCFZc6aC6YE-96-2581-2607
- ⏱ 2022-08-03 00:27:54
58.2 unsafe包的典型应用
- 📌 可以通过unsafe包实现性能更好的类型转换。最常见的类型转换是string与[]byte类型间的相互转换 ^CB-88q19I1CCFZc6aC6YE-97-5573-5626
- ⏱ 2022-08-03 10:32:46
58.3 正确理解unsafe.Pointer与uintptr
-
📌 unsafe.Pointer和其他常规类型指针一样,可以作为对象引用。 ^CB-88q19I1CCFZc6aC6YE-98-798-833
- ⏱ 2022-08-03 10:47:57
-
📌 Go使用的是连续栈的栈管理方案,每个goroutine的默认栈大小为2KB(_StackMin = 2048)。当goroutine当前剩余栈空间无法满足函数/方法调用对栈空间的需求时,Go运行时就会新分配一块更大的内存空间作为该goroutine的新栈空间,并将该goroutine的原有栈整体复制过来,这样原栈上分配的变量的地址就会发生变化。 ^CB-88q19I1CCFZc6aC6YE-98-3351-3612
- ⏱ 2022-08-03 10:58:48
58.4 unsafe.Pointer的安全使用模式
-
📌 unsafe.Pointer -> uintptr -> unsafe.Pointer的转换要在一个表达式中 ^CB-88q19I1CCFZc6aC6YE-99-5389-5443
- ⏱ 2022-08-03 11:31:46
-
📌 reflect包的SliceHeader和StringHeader两个结构体分别代表着切片类型和string类型的内存表示。 ^CB-88q19I1CCFZc6aC6YE-99-8310-8372
- ⏱ 2022-08-03 14:22:31
-
📌 模式1:*T1 -> unsafe.Pointer -> *T2 ^CB-88q19I1CCFZc6aC6YE-99-706-738
- ⏱ 2022-08-03 14:24:35
59.1 Go反射的三大法则
-
📌 在使用反射时需要牢记这三条法则。反射世界的入口:经由接口(interface{})类型变量值进入反射的世界并获得对应的反射对象(reflect.Value或reflect.Type)。反射世界的出口:反射对象(reflect.Value)通过化身为一个接口(interface{})类型变量值的形式走出反射世界。修改反射对象的前提:反射对象对应的reflect.Value必须是可设置的(Settable)。 ^CB-88q19I1CCFZc6aC6YE-101-3977-4306
- ⏱ 2022-08-03 14:50:09
-
📌 图59-1 Go变量与反射对象之间的转换关系 ^CB-88q19I1CCFZc6aC6YE-101-4758-4780
- ⏱ 2022-08-03 14:53:26
59.2 反射世界的入口
- 📌 reflect.TypeOf和reflect.ValueOf是进入反射世界仅有的两扇“大门”。 ^CB-88q19I1CCFZc6aC6YE-102-350-563
- ⏱ 2022-08-03 14:58:02
59.4 输出参数、interface{}类型变量及反射对象的可设置性
-
📌 当被反射对象以指针类型(*T或&T)传递给reflect.ValueOf时,通过reflect.Value的Elem方法可以得到代表该指针所指内存对象的Value反射对象。而这个反射对象是可设置和可寻址的,对其进行修改(比如利用Value的SetInt方法)将会像函数的输出参数那样直接修改被反射对象所指向的内存空间的值。 ^CB-88q19I1CCFZc6aC6YE-104-6238-6556
- ⏱ 2022-08-03 15:38:20
-
📌 map类型被反射对象比较特殊,它的key和value都是不可寻址和不可设置的。但我们可以通过Value提供的SetMapIndex方法对map反射对象进行修改,这种修改会同步到被反射的map变量中。 ^CB-88q19I1CCFZc6aC6YE-104-7369-7468
- ⏱ 2022-08-03 15:39:31
-
📌 当传入结构体或数组指针时,通过Field或Index方法得到的代表结构体字段或数组元素的Value反射对象也是可设置和可寻址的。如果结构体中某个字段是非导出字段,则该字段是可寻址但不可设置的(比如上面例子中的age字段)。 ^CB-88q19I1CCFZc6aC6YE-104-6586-7016
- ⏱ 2022-08-03 15:41:17
-
📌 当被反射对象以值类型(T)传递给reflect.ValueOf时,所得到的反射对象(Value)是不可设置和不可寻址的。 ^CB-88q19I1CCFZc6aC6YE-104-6148-6208
- ⏱ 2022-08-03 15:43:18
60.1 Go调用C代码的原理
- 📌 import “C”这行语句是必须有的,而且其与上面的C代码之间不能用空行分隔,必须紧密相连。这里的“C”不是包名,而是一种类似名字空间的概念,也可以理解为伪包名,C语言所有语法元素均在该伪包下面。 ^CB-88q19I1CCFZc6aC6YE-106-1247-1434
- ⏱ 2022-08-03 15:54:59
60.2 在Go中使用C语言的类型
- 📌 Go将union类型看成[N]byte,其中N为union类型中最长字段的大小 ^CB-88q19I1CCFZc6aC6YE-107-6185-6224
- ⏱ 2022-08-03 17:19:24
60.3 在Go中链接外部C库
- 📌#cgo指示符 ^CB-88q19I1CCFZc6aC6YE-108-564-571
- ⏱ 2022-08-03 17:24:19
61.2 Go module:Go包依赖管理的生产标准
-
📌 一个仓库的顶层目录下会放置一个go.mod文件,每个go.mod文件唯一定义了一个module。一个module就是由一组相关包组成的一个独立的版本单元。 ^CB-88q19I1CCFZc6aC6YE-115-2145-2635
- ⏱ 2022-08-03 20:23:45
-
📌 放置go.mod文件的目录被称为module root目录。module root目录及其子目录下的所有Go包均归属于该module,除了那些自身包含go.mod文件的子目录。 ^CB-88q19I1CCFZc6aC6YE-115-2666-2754
- ⏱ 2022-08-03 20:25:16
-
📌 在module-aware模式下,Go编译器将下载的依赖包缓存在$GOPATH/pkg/mod下 ^CB-88q19I1CCFZc6aC6YE-115-4526-4574
- ⏱ 2022-08-03 20:29:47
-
📌 go命令会在当前目录、当前目录的父目录、父目录的父目录等下面寻找go.mod文件,所找到的第一个go.mod文件对应的module即为main module。 ^CB-88q19I1CCFZc6aC6YE-115-13814-14085
- ⏱ 2022-08-03 20:41:01
-
📌 go.sum记录每个依赖库的版本和对应内容的校验和。 ^CB-88q19I1CCFZc6aC6YE-115-27692-27718
- ⏱ 2022-08-03 20:58:51
-
📌 go命令会使用这些校验和与缓存在本地的依赖包副本元信息进行比对校验。 ^CB-88q19I1CCFZc6aC6YE-115-27768-27802
- ⏱ 2022-08-03 20:59:26
-
📌 go.sum文件不应被用于理解依赖关系,它只是一个元信息数据库。随着项目依赖的演进与变更,go.sum文件中会存储一个module的多个版本信息,即使某个版本已经不再被当前module所依赖。 ^CB-88q19I1CCFZc6aC6YE-115-28653-28749
- ⏱ 2022-08-03 21:02:31
-
📌 在将代码提交/推回存储库之前,请运行go mod tidy以确保module文件(go.mod)是最新且准确的。 ^CB-88q19I1CCFZc6aC6YE-115-28844-28900
- ⏱ 2022-08-04 00:22:29
-
📌 最小版本选择 ^CB-88q19I1CCFZc6aC6YE-115-19986-19992
- ⏱ 2022-08-04 07:16:34
-
📌 在module-aware模式下,由于go.mod和go.sum都是由Go工具链维护和管理的,不建议手动修改go.mod中require中的包版本号。 ^CB-88q19I1CCFZc6aC6YE-115-29153-29228
- ⏱ 2022-08-04 07:29:18
62.1 镜像:继承中的创新
- 📌 LXC是一种内核级虚拟化技术,主要基于Namespaces和Cgroups技术,实现共享一个操作系统内核前提下的进程资源隔离 ^CB-88q19I1CCFZc6aC6YE-119-696-758
- ⏱ 2022-08-04 08:31:21
64.3 构建
-
📌 下面介绍一些常用的编译器命令行标志选项。-l:关闭内联。-N:关闭代码优化。-m:输出逃逸分析(决定哪些对象在栈上分配,哪些对象在堆上分配)的分析决策过程。-S:输出汇编代码。 ^CB-88q19I1CCFZc6aC6YE-130-10097-10340
- ⏱ 2022-08-04 10:11:52
-
📌 go build可以经由-gcflags向compile工具传递编译所需的命令行标志选项集合。 ^CB-88q19I1CCFZc6aC6YE-130-9341-9528
- ⏱ 2022-08-04 10:13:25
-
📌 -ldflags:传给链接器的标志选项集合 ^CB-88q19I1CCFZc6aC6YE-130-10888-10910
- ⏱ 2022-08-04 10:18:00
-
📌 -X:设定包中string类型变量的值(仅支持string类型变量)。 ^CB-88q19I1CCFZc6aC6YE-130-11209-11244
- ⏱ 2022-08-04 10:22:17
-
📌 当一个Go源文件带有build tag时,只有当该组tag被求值为true时,该源文件才会被包含入对应的包中参与构建。 ^CB-88q19I1CCFZc6aC6YE-130-14743-14802
- ⏱ 2022-08-04 10:37:09
-
📌 go build可以通过-tags指定构建的约束条件,以决定哪些源文件被包含在包内进行构建。t ^CB-88q19I1CCFZc6aC6YE-130-12928-13089
- ⏱ 2022-08-04 10:41:53
-
📌 与tags值列表中的tag1、tag2等呼应的则是Go源文件中的buildtag(亦称为buildconstraint)。 ^CB-88q19I1CCFZc6aC6YE-130-13190-13666
- ⏱ 2022-08-04 10:42:15
-
📌 build tag行也是注释,它以+build作为起始标记,与前面的注释符号//中间有一个空格。+build后面就是约束标记字符串,比如上面例子中的aix、darwin等。每一行的build tag实质上会被求值为一个布尔表达式。 ^CB-88q19I1CCFZc6aC6YE-130-13939-14282
- ⏱ 2022-08-04 10:43:34
64.4 运行与诊断
-
📌 Go还提供了一个可以调节GC触发时机的环境变量:GOGC。GOGC是一个整数值,默认为100。这个值代表一个比例值,100表示100%。这个比例值的分子是上一次GC结束后到当前时刻新分配的堆内存大小(设为M),分母则是上一次GC结束后堆内存上的活动对象内存数据(live data,可达内存)的大小(设为N)。 ^CB-88q19I1CCFZc6aC6YE-131-1681-2025
- ⏱ 2022-08-04 10:55:33
-
📌 三色标记清除 ^CB-88q19I1CCFZc6aC6YE-131-3996-4002
- ⏱ 2022-08-04 11:03:57
-
📌 提前启动 ^CB-88q19I1CCFZc6aC6YE-131-4284-4288
- ⏱ 2022-08-04 11:31:13
-
📌 究竟该提前多久启动新一轮GC呢?这是由Go并发垃圾回收的Pacing算法决定的。 ^CB-88q19I1CCFZc6aC6YE-131-4449-4489
- ⏱ 2022-08-04 11:34:54
-
📌 调节用户goroutine参与清除及标记的时间比例。如果某用户goroutine分配内存过快,该算法就会延缓其分配速度,让其更多地参与清除或辅助扫描标记的工作。 ^CB-88q19I1CCFZc6aC6YE-131-5051-5131
- ⏱ 2022-08-04 11:37:25
-
📌 可以通过设置环境变量GODEBUG=‘gctrace=1’让位于Go程序中的运行时在每次GC执行时输出此次GC相关的跟踪信息。 ^CB-88q19I1CCFZc6aC6YE-131-5211-5274
- ⏱ 2022-08-04 11:43:15
-
📌 GODEBUG=schedtrace=1000 ^CB-88q19I1CCFZc6aC6YE-131-11326-11349
- ⏱ 2022-08-04 11:54:31
-
📌 即每1000毫秒(1秒)输出一次goroutine调度器的内部信息。 ^CB-88q19I1CCFZc6aC6YE-131-12167-12201
- ⏱ 2022-08-04 11:54:37
64.5 格式化与静态代码检查
-
📌 loopclosure规则:检查源文件中是否存在循环内的匿名函数引用循环变量的问题。 ^CB-88q19I1CCFZc6aC6YE-132-4962-5004
- ⏱ 2022-08-04 12:14:52
-
📌 golangci-lint聚合了几十种Go lint工具 ^CB-88q19I1CCFZc6aC6YE-132-7053-7081
- ⏱ 2022-08-04 12:19:28
64.7 查看文档
- 📌 查看标准库包源码:$go doc -src fmt.Printf ^CB-88q19I1CCFZc6aC6YE-134-4269-4323
- ⏱ 2022-08-04 15:39:32
65.2 go generate的工作原理
- 📌 将Go源码文件当成普通文本读取并识别其中可以与下面字符串模式匹配的内容(go generate指示符)://go:generate command arg…注意,注释符号//前面没有空格,与go:generate之间亦无任何空格。 ^CB-88q19I1CCFZc6aC6YE-138-1204-1362
- ⏱ 2022-08-04 16:26:59
65.3 go generate的应用场景
-
📌 go generate驱动生成枚举类型的String方法 ^CB-88q19I1CCFZc6aC6YE-139-664-692
- ⏱ 2022-08-04 16:18:17
-
📌 //go:generate stringer -type=Weekday ^CB-88q19I1CCFZc6aC6YE-139-1959-1997
- ⏱ 2022-08-04 16:19:55
-
📌 通过go:embed指示符将静态资源文件嵌入 ^CB-88q19I1CCFZc6aC6YE-139-4229-4251
- ⏱ 2022-08-04 16:22:56
66.1 语法规范类
-
📌 由于不在同一个代码块中,编译器没有在同一代码块里找到与b, err := bar()这行代码中err同名的变量,因此会声明一个新err变量,该err变量也就顺理成章地遮蔽了main函数代码块中的err变量。 ^CB-88q19I1CCFZc6aC6YE-141-4554-4657
- ⏱ 2022-08-04 16:34:37
-
📌 在同一个代码块(block)中 ^CB-88q19I1CCFZc6aC6YE-141-2309-2324
- ⏱ 2022-08-04 16:35:20
-
📌 在不同代码块层次上使用多变量短声明形式会带来难以发现的变量遮蔽问题,从而导致程序运行异常。通过go vet+shadow工具可以很快捷方便地发现这一问题。 ^CB-88q19I1CCFZc6aC6YE-141-5068-5145
- ⏱ 2022-08-04 16:46:35
-
📌 接口类型在运行时的表示分为两部分,一部分是类型信息,一部分是值信息。只有当接口类型变量的这两部分的值都为nil时,该变量才与nil相等。 ^CB-88q19I1CCFZc6aC6YE-141-8303-8371
- ⏱ 2022-08-04 16:57:51
-
📌 在“复制品”上进行迭代 ^CB-88q19I1CCFZc6aC6YE-141-13829-13840
- ⏱ 2022-08-04 17:05:04
-
📌 采用值类型receiver的方法无法改变类型实例的状态。 ^CB-88q19I1CCFZc6aC6YE-141-34199-34227
- ⏱ 2022-08-04 17:49:25
66.2 标准库类
-
📌 空切片被编码为[],而nil切片则被编码为null ^CB-88q19I1CCFZc6aC6YE-142-4314-4339
- ⏱ 2022-08-04 17:59:30
-
📌 字节切片被编码为一个base64编码的文本 ^CB-88q19I1CCFZc6aC6YE-142-4899-4920
- ⏱ 2022-08-04 18:01:35
-
📌 当JSON文本中的整型数值被解码为interface{}类型时,其底层真实类型为float64 ^CB-88q19I1CCFZc6aC6YE-142-5312-5359
- ⏱ 2022-08-04 18:17:17
-
📌 d.UseNumber() ^CB-88q19I1CCFZc6aC6YE-142-7102-7117
- ⏱ 2022-08-04 18:20:30
-
📌 age, _ := m[“age”].(json.Number).Int64() ^CB-88q19I1CCFZc6aC6YE-142-7145-7187
- ⏱ 2022-08-04 18:20:51
-
📌 目前http包的实现逻辑是只有当应答的Body中的内容被全部读取完毕且调用了Body.Close(),默认的HTTP客户端才会重用带有keep-alive标志的HTTP连接,否则每次HTTP客户端发起请求都会单独向服务端建立一条新的TCP连接,这样做的消耗要比重用连接大得多。注:仅在作为客户端时,http包才需要我们手动关闭Response.Body;如果是作为服务端,http包会自动处理Request.Body。 ^CB-88q19I1CCFZc6aC6YE-142-8612-8847
- ⏱ 2022-08-04 18:24:45
-
📌 HTTP客户端默认不会及时关闭已经用完的HTTP连接 ^CB-88q19I1CCFZc6aC6YE-142-8980-9006
- ⏱ 2022-08-04 18:29:49
-
📌 及时释放HTTP连接的方法有两种,第一种是将http.Request中的字段Close设置为true ^CB-88q19I1CCFZc6aC6YE-142-9348-9398
- ⏱ 2022-08-04 18:31:42
-
📌 第二种方法是通过创建一个http.Client新实例来实现的(不使用DefaultClient) ^CB-88q19I1CCFZc6aC6YE-142-10817-10865
- ⏱ 2022-08-04 18:32:13
-
📌 DisableKeepAlives: true, ^CB-88q19I1CCFZc6aC6YE-142-11032-11058
- ⏱ 2022-08-04 18:32:31