既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
而读写锁是可以允许多个goroutine获取到读锁执行读操作,但是写锁被获取了就和互斥锁一样了,其他goroutine必须等待写锁释放才能获取到读锁或者写锁。
sync
- sync包还有什么?sync.map介绍一下?如何保证并发安全?
sync.waitgroup, sync.map ,sync.Lock, sync.RWLock,sync.Pool…
sync.map 底层有两个map,一个是read,一个是dirty, 在读操作时优先在read中查找,read没有就去dirty中查找,写操作时如果read中有则利用CAS机制尝试更新value值,read中没有则写入 dirty 中。在 misses >= len(dirty)时,同步read 和 dirty的数据。
在read中不需要加锁,在dirty中需要加锁
sync.map通过read和dirty实现读写分离来减少锁时间来提高并发效率
协程池
- sync.Pool?了解线程池吗?优势亮点?未工作的线程如何等待?协程池?
sync.Pool 其实就是一个线程安全的对象池,用于保存和复用临时对象,在大批量申请和释放相同类型的临时对象时使用 sync.Pool 可以减少很多内存分配和回收操作,减小GC压力。
线程池是一种并发编程的技术,可以管理和复用线程,提供一种高效的方式来处理并发。
线程池优势亮点:
- 提高性能,线程池通过复用线程,减少线程频繁地创建和销毁,避免线程的频繁创建和销毁的开销。
- 控制并发度,线程池可以控制并发任务的数量,通过设计线程池的大小来控制并发度,避免激烈的锁竞争导致系统性能的下降。
- 提高响应速度, 线程池可以提前创建好线程,在任务到来时可以立即处理任务,提高系统的响应速度。
- 资源管理,线程池可以更好的对线程进行调度和管理,避免线程资源的浪费。
未工作的线程可以通过以下方式等待:
- 使用条件变量:线程可以使用条件变量来等待某个条件的发生。当线程需要等待时,它可以调用条件变量的等待函数,将自己置于等待状态,直到条件满足时被唤醒。
- 使用信号量:线程可以使用信号量来进行等待操作。线程在需要等待时,可以调用信号量的等待操作,将自己阻塞,直到其他线程释放信号量时被唤醒。
- 使用锁和条件变量组合:线程可以使用锁和条件变量的组合来实现等待操作。线程在需要等待时,可以先获取锁,然后检查条件是否满足,如果条件不满足,则调用条件变量的等待函数将自己置于等待状态,直到条件满足时被唤醒。
协程池和线程池基本差不多,可以更好地管理和复用协程,提高系统的性能和资源利用率。
协程泄露
- 防止Go协程泄露/未关闭?(waitgroup,context)
通过管道channel通知关闭,使用waitgroup监控协程全部退出,使用contex上下文来设置超时或者手动cancle关闭协程
select的用法?执行顺序?
select{
case <-ctx.Done():
return
case <-
default:
}
执行顺序是随机的
map
- 什么可以作为map的键?结构体可以吗?
实现了 == 操作的可以比较的就可以作为map的键(基本数据类型、数组等),结构体中如果所有字段都可以比较那么久可以作为键,否则不行。
微服务
- 微服务之间通信方式 rpc、grpc、http等
介绍一下grpc?protobuf/json区别与优势?
GRPC是一种高性能、开源的远程过程调用(RPC)框架,由Google开发并基于HTTP/2协议实现。它允许在不同的计算机之间进行跨语言和跨平台的通信,使得构建分布式系统变得更加简单和高效。
GRPC使用Protocol Buffers(简称Protobuf)作为默认的序列化机制,而不是使用JSON。
Protobuf是一种轻量级的数据交换格式,具有以下优势:
- 效率高:Protobuf使用二进制编码,相比于文本格式的JSON,它的编码和解码速度更快,传输的数据量更小,节省了带宽和存储空间。
- 可读性好:虽然Protobuf是二进制格式,但它的定义文件是可读的,易于理解和维护。相比之下,JSON是一种文本格式,可读性较好,但在大型数据结构的情况下,Protobuf的定义文件更加清晰和简洁。
- 跨语言支持:Protobuf支持多种编程语言,包括Java、C++、Python等,这使得在不同语言之间进行通信变得更加方便。
- 版本兼容性:Protobuf支持向后和向前兼容的数据格式演化,这意味着可以在不破坏现有客户端和服务端的情况下,对数据结构进行扩展和修改。
相比之下,JSON是一种常用的文本格式,具有以下特点:
- 可读性好:JSON使用文本格式,易于阅读和理解,对于调试和开发过程中的数据交换非常方便。
- 平台无关性:JSON是一种独立于编程语言的数据格式,几乎所有的编程语言都支持JSON的解析和生成。
- 灵活性:JSON支持动态的数据结构,可以轻松地添加、删除和修改字段,适用于一些需要频繁变动的数据。
总的来说,GRPC使用Protobuf作为默认的序列化机制,相比于JSON,Protobuf在性能、可读性和跨语言支持方面具有优势。然而,选择使用GRPC还是JSON取决于具体的应用场景和需求。
介绍一下Gorm优势?
简单易用、支持多种数据库、自动迁移、支持事务、
Redis
1.常见数据结构
答:(字符串、set、zset、hash、list…)
hash和zset底层使用 skiplist 和 ziplist,同时满足两个条件时使用 ziplist,否则 skiplist
- 集合元素个数小于redis.conf 中 zset-max-ziplist-entries 属性的值,其默认值为128
- 每个集合元素大小都小于 redis.conf 中 zset-max-ziplist-value 属性的值,其默认值为 64 字节
list 底层使用了快表(quicklist),quickList 本质上是 zipList 和 linkedList 的混合体。其将 linkedList 按段切分,每一段使用 zipList 来紧凑存储若干真正的数据元素,多个 zipList 之间使用双向指针串接起来。对于每个zipList 中最多可存放多大容量的数据元素,在配置文件中通过 list-max-ziplist-size 属性可以指定。
2.zset介绍一下?zset底层借助那些数据结构实现?跳表介绍一下?查找过程?复杂度?
zset是redis中的有序集合,借助了跳表和哈希表(哈希表存储成员和对应的分数)实现有序集合,跳表是一种有序的链表结构,它通过在每个节点中维护多个指针,使得在查找和插入操作时可以跳过部分节点,从而提高了查找的效率。跳表的高度是通过随机函数决定的,因此在平均情况下,查找的时间复杂度为O(log n),其中n是跳表中的节点数量。
3.set介绍?
set 底层使用哈希表。
4.压缩列表介绍?
压缩列表的设计目标是在尽可能节省内存的同时,提供高效的插入、删除和访问操作。它通过使用连续的内存块来存储数据,减少了指针和额外的元数据开销,从而节省了内存空间。
5.渐进式rehash?
渐进式rehash是Redis在进行哈希表扩容时采用的一种策略。当哈希表需要扩容时,Redis会创建一个新的哈希表,并将原有哈希表中的数据逐步迁移到新的哈希表中。这个过程是逐步进行的,每次只迁移一小部分数据,以避免在一次性迁移过程中对系统性能造成较大的影响。
渐进式rehash的过程如下:
- Redis会创建一个新的空哈希表,大小是原有哈希表的两倍。
- Redis会将原有哈希表中的一个桶(bucket)中的键值对逐个迁移到新的哈希表中。这个迁移过程是逐个键值对进行的,而不是一次性迁移整个桶。
- 在每次迁移过程中,Redis会将新哈希表中对应的桶指向原有哈希表中的桶,以保持对原有哈希表的访问能力。
- 迁移完成后,Redis会将新哈希表设置为当前使用的哈希表,并释放原有哈希表的内存空间。
通过渐进式rehash,Redis可以在不中断服务的情况下进行哈希表的扩容。这种方式可以避免在一次性迁移过程中对系统性能造成较大的影响,因为每次只迁移一小部分数据。同时,渐进式rehash还可以保持对原有哈希表的访问能力,确保在迁移过程中数据的一致性。
更多面经
下面的面经同样精彩,希望对大家找工作有帮助:
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
A-1715712189801)]
[外链图片转存中…(img-ElAGAHzi-1715712189801)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新