Please enable Javascript to view the contents

Go-面试速记-八股文

 ·  ☕ 4 分钟

1. GMP调度模型

G: goroutine,是主要的执行体
M: 线程,每个协程都会被分配到响应的线程进行执行
P: 是线程的上下文,会维护一个本地goroutine队列。

working-steal机制: 本地goroutine队列空后,回去全局G队列获取G执行,当全局G队列也空之后,则会去其他M绑定的P中窃取G执行

2. golang的gc

三色标记混合写屏障

3. 什么是heap,什么是栈,以及各自存储什么数据

代码的本质:主要包含两部分:指令部分(cpu可执行的指令)、数据部分(常量等)。

代码执行:可执行文件加载到内存中,cpu通过内存取指(cpu控制单元-从内存获取指令)、译值(cpu控制单元-解析获取的指令)、执行(cpu运算单元-执行具体指令)

内存的作用:1. 暂存可执行文件中的指令、预置数据;2. 暂存执行过程中的中间数据;

栈内存:计算机对连续内存的采取线性分配的管理方式,便于高效存储指令运行过程中的临时变量(连续内存的线性分配,目的:简单高效的分配和回收内存)内存分配=入栈,内存回收=出栈。

4. slice与array的区别是什么?

共性:都是一组同一类型元素组成的序列,通过索引获取元素,len和cap获取长度和容量。

区别:

数组切片
定义数组是切片的底层数据结构切片又称动态数组,是基于数组类型的封装(slice是对array一段连续片段的引用)
容量、长度在创建时就确定,且不可变可变长
类型值类型(作为func的参数传入时,将复制一份数组,而非传入同一个指针)引用类型(作为func的参数传入时,传入指针)
使用频率极少(一般最为内置类型,极少在业务代码中使用)

slice拷贝:
内置函数copy可拷贝两个切片,会将s_slice的数据逐个拷贝到d_slice所指向的数组中,拷贝过程不会扩容。(即len(s_slice)=10, len(d_slice)=5时,只拷贝前5个元素)

slice扩容:

内置函数append可向切片插入元素,当append函数发现len超出cap时,会发生slice扩容。(扩容操作只关心容量)

扩容实际上是分配一块更大的内存,将原slice的数据拷贝进新slice,然后返回新slice,扩容后再将数据追加进去。

扩容规则:

1
2
3
4
5
if cap(slice) < 1024{
    cap(slice) = 2 * cap(slice)
} else {
    cap(slice) = 1.25 * cap(slice)
}

Python切片与Go切片有何不同?

最大的不同:

Python的切片产生的是新的对象,对新对象的成员的操作不影响旧对象;

Go的切片产生的是旧对象一部分的引用,对其成员的操作会影响旧对象;

其他不同

  1. Go的切片,是相同类型元素组成的序列;Python的列表则不限制类型。
  2. Go的切片操作[a:b]不能为负数;Python可以,即允许从末尾向前引用。
  3. Go的切片操作[a🅱️c]中,c是容量;Python中的c是步长。

原因:底层实现不同

  • Go的切片,底层是一个三元组。指针指向一块连续的内存,长度是已有成员数,容量是最大成员数。对它切片,是对原指针的移动,而非申请新的内存(Go的切片操作通常会和生成该切片的切片或数组共享内存。)
  • Python的切片,其实就是指针数组。对它进行切片,会创建新的数组。在Python的切片中,并没有容量的概念。

slice

5. channel在使用中的注意事项(有无缓存; 写数据、读数据; 关闭channel)?

6. Mutex锁在使用中有什么注意事项?

  1. Go的锁不可以重入
  2. 锁不具备绑定关系,必须遵循谁申请,谁释放的原则(协程可以释放别的协程的锁,导致data-race问题)。

7. 有哪些类型是引用类型,哪些是值类型?

8. 有哪些类型是线程安全的?

分享

Hex
作者
Hex
CloudNative Developer

目录