Golang开发面试题汇总
请分析以下代码两个方法的执行效率,哪个更快,为什么?
1 |
|
行优先与列优先问题,因CPU会遵从局部性原理,总是习惯于从连续的一片内存地址中读取。延展问题:如果CPU在多核状态下读取cache,如何保证缓存一致性,MESI协议的四个cache状态介绍。
以下代码的执行结果是什么?并简单解释为什么?
1 |
|
切片基本运用,延展问题:切片在Go当中是什么类型的数据?
切片的扩容机制是什么,如果有一个长度5000的切片,扩容之后会变成多少?
slice 可变数组;
切片的底层是引用数组类型,所以切片是引用类型扩容机制:
预估容量,内存对齐
channel是否是线程安全的?基于什么实现线程安全的?无缓冲与有缓冲的区别是什么?如何利用channel来控制goroutine执行顺序?简单描述下channel的底层数据结构。
Golang的Channel,发送一个数据到Channel 和从Channel接收一个数据都是原子性的
实际上缓冲区就是一个数组
1 |
|
ch 是存在于函数栈上的一个指针,指向堆上的 hchan结构,channl底层结构:
- 支持协程间并发访问, lock mutex
- 有缓冲区,需要知道缓冲区在哪: buf unsafe.Pointer
- 缓冲区已经存储了多少个元素qcount unit
- 缓冲区最多存储多少个元素 dataqsiz unit
- 每个元素站多大空间 elemsize uint16
- golang运行中,内存复制 垃圾回收等机制,还需要知道缓冲区依赖数据的类型信息
所以还需要一个指针,指向元素类洗净的元数据 elemtype *_type - channel 支持交替的读写,需要分别记录读和写的下标位置 sendx uint,recvx unit
- 当读和写不能立即完成时,需要能够让当前协程在channel上等待,所以需要两个等待队列,针对读和写:recvq waitq, sendq waitq
- channel可以close,所以需要一个字段记录close状态:closed unit32
chanel缓冲区被称为环形缓冲区
如果可以请利用channel写一个简单的控制流程代码,要求创建两个goroutine,一个打印字符串“hello”,另一个打印字符串“world”,最终结果无论执行多少次都必须先输出hello,再输出world。
channel的基本使用,利用通道阻塞(锁)来实现。
1 |
|
map是否是线程安全的?如何解决这一问题?代价是什么?如何减小锁的颗粒级别?
并发处理的简单应用。将map按业务颗粒拆成多个维度,将多协程竞争一把锁改成多协程竞争多把锁。
在并发情况下,只读是线程安全的,同时读写是线程不安全的。
需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构。Store 表示存储,Load 表示获取,Delete 表示删除。
一般情况下解决并发读写 map 的思路是加一把大锁,或者把一个 map 分成若干个小 map,对 key 进行哈希,只操作相应的小 map。前者锁的粒度比较大,影响效率;后者实现起来比较复杂,容易出错。
而使用 sync.map
之后,对 map 的读写,不需要加锁。并且它通过空间换时间的方式,使用 read 和 dirty 两个 map 来进行读写分离,降低锁时间来提高效率。
Golang中有哪几种锁类型?Mutex与RWMutex的区别是什么?Mutex是乐观锁还是悲观锁,简单介绍一下RWMutex的底层数据结构。
延展问题:Mutex锁有几种模式?什么情况下会触发饥饿模式,什么情况下会取消饥饿模式?
简单介绍一下GMP模型。如果某个G发生自旋一直占用CPU,Go会如何解决这个问题?
延展问题:超过一定时间后,Go的调度器会抢占回来,抢占的时机是STW。
简单阐述一下Go中会产生逃逸的几种场景。
延展问题:你是如何分析逃逸的,会借助什么样的工具? gcflags
简单介绍下你之前使用过的框架是如何实现优雅启停的,信号与信号量的区别,信号量与互斥量的区别?
延展问题:Linux有多少种信号,可靠与非可靠的区别?可以举例几个常见的信号么?
线程与协程的 区别是什么?可以简单介绍下用户态与内核态的区别么?
Linux操作系统的基础了解。
MySQL当中为什么通常主键ID都是自增的,有什么样的考虑?什么是覆盖索引?什么是前缀索引?如果对前缀索引字段进行排序,可以命中索引吗
底层数据结构和聚簇非聚簇索引的了解。延展问题:MySQL是利用什么机制来保障事务的ACID?MVCC只针对哪两个隔离级别起作用?为什么?
MySQL优化器什么情况下不会使用索引?如果有联合索引(a、b、c),查询条件为 :
1 |
|
分别会命中索引吗?为什么?
其他
kafka为什么性能好?从底层存储的实现以及架构上(partion),kafka中有哪些默认分区策略(key传没传,hash取模,轮询,随机(轮序和随机在有无可用分区的情况下是怎么切换的)),ConsumerGroup的理解(什么时候触发重平衡,基本流程是什么)
- make 和 new 的区别﹖
- 了解过golang的内存管理吗?
- 调用函数传入结构体时,应该传值还是指针﹖说出你的理由?
- 线程有几种模型?Goroutine的原理了解过吗,讲一下实现和优势?
- Goroutine什么时候会发生阻塞?
- PMG模型中Goroutine有哪几种状态?
- 每个线程/协程占用多少内存知道吗?
- 如果Goroutine—直占用资源怎么办,PMG模型怎么解决的这个问题?
- 如果若干线程中一个线程OOM,会发生什么?如果是Goroutine 呢? 项目中出现过OOM吗,怎么解决的?
- 项目中错误处理是怎么做的?
- 如果若干个Goroutine,其中有一个panic,会发生什么?
- defer可以捕获到其Goroutine的子Goroutine 的panic吗?
- 开发用Gin框架吗?Gin怎么做参数校验?
- 中间件使用过吗?怎么使用的。Gin的错误处理使用过吗?Gin中自定义校验规则知道怎么做吗?自定义校验器的返回值呢?
- golang中解析tag是怎么实现的?反射原理是什么?通过反射调用函数
- golang的锁机制了解过吗? Mutex的锁有哪几种模式,分别介绍一下? Mutex锁底层如何实现了解过吗?
- channel、channel使用中需要注意的地方?
- 数据库用的什么?数据库锁有了解吗?mysql锁机制讲一下。mysql分库分表。
- 讲一下redis分布式锁?redis主从模式和集群模式的区别了解过吗?redis的数据类型有哪些?redis持久化怎么做的?
- 编程题:你了解的负载均衡算法有什么?实现一个负载均衡算法。