计算机知识图谱——编程语言

计算机 ==>> 编程语言

编程语言

golang

数据类型

切片

切片引入了一个抽象层,提供了对数组中部分连续片段的引用,而作为数组的引用,我们可以在运行区间可以修改它的长度和范围。当切片底层的数组长度不足时就会触发扩容,切片指向的数组可能会发生变化(未发生扩容的情况下底层数组发生变化),不过在上层看来切片是没有变化的,上层只需要与切片打交道不需要关心数组的变化。

当切片的容量不足时,我们会调用 runtime.growslice 函数为切片扩容,扩容是为切片分配新的内存空间并拷贝原切片中元素的过程。在分配内存空间之前需要先确定新的切片容量,运行时根据切片的当前容量选择不同的策略进行扩容:

如果期望容量大于当前容量的两倍就会使用期望容量;
如果当前切片的长度小于 1024 就会将容量翻倍;
如果当前切片的长度大于 1024 就会每次增加 25% 的容量,直到新容量大于期望容量;

runtime.roundupsize 函数会将待申请的内存向上取整,取整时会使用 runtime.class_to_size 数组,使用该数组中的整数可以提高内存的分配效率并减少碎片。

1
2
3
4
5
6
7
8
9
10
var class_to_size = [_NumSizeClasses]uint16{
0,
8,
16,
32,
48,
64,
80,
...,
}
哈希表

开放地址法

开放寻址法中对性能影响最大的是装载因子,它是数组中元素的数量与数组大小的比值。随着装载因子的增加,线性探测的平均用时就会逐渐增加,这会影响哈希表的读写性能。当装载率超过 70% 之后,哈希表的性能就会急剧下降,而一旦装载率达到 100%,整个哈希表就会完全失效,这时查找和插入任意元素的时间复杂度都是 O(n) 的,这时需要遍历数组中的全部元素,所以在实现哈希表时一定要关注装载因子的变化。

拉链法

装载因子:=元素数量÷桶数量。与开放地址法一样,拉链法的装载因子越大,哈希的读写性能就越差。在一般情况下使用拉链法的哈希表装载因子都不会超过 1,当哈希表的装载因子较大时会触发哈希的扩容,创建更多的桶来存储哈希中的元素,保证性能不会出现严重的下降。如果有 1000 个桶的哈希表存储了 10000 个键值对,它的性能是保存 1000 个键值对的 1/10,但是仍然比在链表中直接读写好 1000 倍。

字符串

字符串只是一个只读的字节数组

协程

线程是操作系统调度的最基本单元,对个线程可以属于同一进程并共享内存空间,线程之间的通讯是基于共享内存进行的

Go 语言的调度器通过使用与 CPU 数量相等的线程减少线程频繁切换的内存开销,同时在每一个线程上执行额外开销更低的 Goroutine 来降低操作系统和硬件的负载。

接口

在 Go 中:实现接口的所有方法就隐式地实现了接口。不关心它实现了哪些接口,只会在传递参数、返回参数以及变量赋值时才会对某个类型是否实现接口进行检查。

Go 语言根据接口类型是否包含一组方法将接口类型分成了两类:使用 runtime.iface 结构体表示包含方法的接口;使用 runtime.eface 结构体表示不包含任何方法的 interface{} 类型。

从上述表格我们可以看到使用结构体实现接口带来的开销会大于使用指针实现,而动态派发在结构体上的表现非常差,这也提醒我们应当尽量避免使用结构体类型实现接口。

关键字

select

select 在遇到多个 <-ch 同时满足可读或者可写条件时会随机选择一个 case 执行其中的代码。

如果我们想实现广播方式我们可能需要将消息写入N个channel,需要创建多个频道。

make

在编译期间的类型检查阶段,Go 语言会将代表 make 关键字的 OMAKE 节点根据参数类型的不同转换成了 OMAKESLICE、OMAKEMAP 和 OMAKECHAN 三种不同类型的节点,这些节点会调用不同的运行时函数来初始化相应的数据结构。

返回的初始化的 T,只能用于 slice,map,channel。

new

返回 T 的指针 *T 并指向 T 的零值。

并发编程

context

树形结构中对信号进行同步以减少计算资源的浪费。

互斥锁

读写锁

调度器

多个线程可以属于同一个进程并共享内存空间。因为多线程不需要创建新的虚拟内存空间,所以它们也不需要内存管理单元处理上下文的切换,线程之间的通信也正是基于共享的内存进行的,与重量级的进程相比,线程显得比较轻量。

虽然线程比较轻量,但是在调度时也有比较大的额外开销。每个线程会都占用 1M 以上的内存空间,在切换线程时不止会消耗较多的内存,恢复寄存器中的内容还需要向操作系统申请或者销毁资源,每一次线程上下文的切换都需要消耗 ~1us 左右的时间1,但是 Go 调度器对 Goroutine 的上下文切换约为 ~0.2us,减少了 80% 的额外开销。

GPM模型:

GC

并发的“三色法”

常见panic

  1. 数组越界

  2. 空指针异常

  3. 类型断言失败

  4. 通道为空、通道已关闭

  5. 死锁

c++

java

python

安装启动

运行

1
python .\metro.py

添加依赖

1
python -m pip install bs4

代码质量管理

SonarQube