Golang面试知识点总结
发布网友
发布时间:2024-09-30 07:11
我来回答
共1个回答
热心网友
时间:2024-11-04 02:45
本文总结了Go语言开发所需掌握的关键知识点,涵盖了语言特性、并发机制、内存管理、数据结构、反射原理等核心内容,旨在帮助开发者构建全面的Go语言知识体系。
### 数组与切片
切片是数组的快照,底层为一个结构体,包含长度、容量和指向数组的指针。切片赋值为结构体赋值,操作切片实质上是对数组指针的修改。值得注意的是,切片的更改会影响到所有引用其底层数组的切片实例。
### 切片扩容
当在切片末尾添加元素时,切片长度加1。若长度未超过原数组容量,返回的仍为指向原数组的切片;否则返回指向新数组的切片,确保扩容后有足够的空间容纳新增元素。
### Defer机制
Defer通过编译器将延迟执行的函数转化为汇编语言中的函数调用。首先,它将Defer函数及其参数入栈,形成链表结构,每个Defer在头部插入栈链表以保持执行顺序。在函数返回时,编译器插入代码执行栈链表中的Defer函数,先保存返回值,然后逐个执行Defer函数,最后返回最终的返回值。Go 1.14对Defer进行了优化,将Defer操作直接移动到return操作的第二步,显著提高了执行效率。
### Map结构
Map由桶数组组成,键值对通过哈希计算分组。Map内部分为桶外和桶内两部分:桶外通过数组映射,桶内通过高八位哈希值的数组进行查找。Map还包括B的扩容次数、溢出桶和哈希种子等重要组件。
### Map冲突处理
在遇到哈希冲突时,Map在桶内寻找空位存储冲突的键值对。当桶内空间不足时,会使用溢出桶,类似于链表结构,遍历完当前桶后,再遍历溢出桶,确保所有元素被正确查找。
### Channel与阻塞协程
Channel内部维护一个缓存环状线性链表,包含锁、容量、进出的索引值和阻塞的协程列表。Channel操作时需加锁,通过索引值判断元素进出,并利用阻塞协程列表迅速唤醒协程。
### Select实现
Select本质上通过数组实现,存储不同类型的case(包括chan、操作类型和接受结构体),随机打乱顺序后逐一执行。当某个chan有元素时,执行取操作;反之,则将当前协程加入阻塞列表,直到有协程执行塞操作唤醒协程。
### Panic与recover
Panic执行时,会先执行当前协程的defer列表和panic列表中的函数。使用recover恢复时,可恢复程序执行,但不会执行出错程序的下一行代码,而是回到recover函数所在函数的上一级函数。defer函数在当前函数返回时执行,即使函数中途panic,recover恢复后,返回值保持零值。
### unsafe.Pointer与uintptr
unsafe.Pointer和uintptr类型可以相互转化。unsafe.Pointer可用于指针操作,但不能进行运算;uintptr支持运算,但不能转化为除unsafe.Pointer外的其他指针类型。两者常用于优化底层操作,如chan、map等结构的直接操作。
### 锁机制
Go的锁机制涉及GMP调度模型,包括channel、select、time、网络IO、sync.Mutex、sync.Waitgroup、atomic等。channel和select通过维护阻塞协程列表实现高效并发控制。time和网络IO底层使用epoll实现多路复用。sync.Mutex、sync.Waitgroup和rwmutex等通过runtime的并发工具来实现锁的加锁和解锁。
### GMP模型与并发
GMP模型中,协程(G)是用户定义的调度单位,内核线程(M)是操作系统最小调度单位,虚拟CPU(P)的数量一般等于CPU核数或倍数。GMP模型允许同时存在多协程,通过全局协程列表和P的协程队列进行调度。协程的切换比线程轻量,减少了系统开销。
### 反射原理
反射通过reflect包提供访问对象类型、值及操作的动态能力。通过Type和Value方法识别接口类型,访问结构体字段,进行动态类型检查、赋值等操作。反射机制虽提供强大功能,但访问结构体字段时可能较慢,且频繁使用TypeOf和ValueOf可能导致GC压力增加。