[面试口话]二: golang基础

1. Go 基础面试问题合集

Go 方法与函数的区别 :

[面试口话]二: golang基础

Go 方法值接收者和指针接收者的区别

[面试口话]二: golang基础

Go 函数返回局部变量的指针是否安全

般来说,局部变量会在函数返回后被销毁,因此被返回的引用就成为了”无所指”的?
用,程序会进入未知状态。
但这在 Go 中是安全的,Go 编译器将会对每个局部变量进行逃逸分析。如果发现局音量的作用域超出该函数,则不会将内存分配在栈上,而是分配在堆上,因为他们不在区,即使释放函数,其内容也不会受影响。

Go 函数参数传递到底是值传递还是引用传递
值传递

Go 内置函数 make 和 new 的区别

[面试口话]二: golang基础

Go 切片面试问题合集

  1. Go array 和 slice 的区别

有固定大小的是array var a 10[int]
没有有固定大小的是 slice var a [int]

[面试口话]二: golang基础

  1. Go slice 深拷贝和浅拷贝

1.深拷贝
拷贝的是数据本身,创造一个新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值
实现深拷贝的方式有 2 种
copy(slice2,slice1)
遍历 append 赋值

2、浅拷贝
浅拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化

实现浅拷贝的方式:默认复制
引用类型的变量,默认赋值操作就是浅拷贝:slice2:=slice1

  1. Go slice 扩容机制

当新元素添加到 slice 时,如若当前的容量不足以存储新元素,slice 就会扩容。这个过程遵循以下原则:

若新需求容量大于原容量的两倍,新容量就设为新需求容量。
若原长度小于 1024,容量就增加一倍。
若原长度大于等于 1024,容量就增加1/4。

  1. Go slice 为什么不是线程安全的:

一句话: slice 底层结构并没有使用加锁等方式,不支持并发读写,所以并不是线程安全的。

首先:
1、线程安全的定义
多个线程访问同一个对象时,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。
若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全

其次 : 2、Go 语言实现线程安全常用的几种方式
互斥锁
读写锁
·原子操作
sync.once
sync.atomic
channel

最后:
slice 底层结构并没有使用加锁等方式,不支持并发读写,所以并不是线程安全的。
举个例:
如果 使用多个 goroutine 对类型为 sice 的变量进行操作,每次输出的值大概率都不会一样,与预期值不一致,slice 在并发执行中不会报错,但是数据会丢失

Go 哈希表面试问题合集

1. Go map 遍历为什么是无序的

1、主要原因如下

map 在遍历时,并不是从固定的0号 bucket 开始遍历的,每次遍历,都会从一个随机值序号的 bucket,再从其中随机的 cell 开始遍历

map 遍历时,是按序遍历 bucket,同时按需遍历 bucket 中和其 overflow bucket 中的cell。
但是 ** map 在扩容后,会发生 key 的搬迁**,这造成原来落在一个 bucket 中的 key搬迁后,有可能会落到其他 bucket 中了,从这个角度看,遍历 map 的结果就不可能是按照原来的顺序了

2、如何有序遍历 map
对 mapkey 先排序,再按照 key 的顺序遍历 map。


2. Go map 为什么是非线程安全的

map 默认是并发不安全的,同时对 map 进行并发读写时,程序会 panic,原因如下Go 官方在经过了长时间的讨论后,认为 Go map 更应适配典型使用场景(不需要从多个goroutine 中进行安全访问),而不是为了小部分情况(并发访问),导致大部分程序付出加锁代价(性能),决定了不支持。
2 个协程同时读和写,以下程序会出现致命错误:fatalerror: concurrent map writes

3. Go map 如何查找

// 带 comma 用法
value, ok := m["name"]
if ok {
fmt.Printf("value:%s", value)
}

4. Go map 冲突的解决方式

在发生哈希冲突时,Python 中 dict 采用的开放寻址法,

Java 的 HashMap 采用的是链地址法,
而 Go map 也采用链地址法解决冲突:
当哈希冲突发生时,创建新单元,并将新单元添加到冲突单元所在链表的尾部。

什么是hash冲突:
在哈希表中,不同的关键字通过 哈希函数计算得到的 ** 哈希值** 却 相同 的情况。
简单来说,就是不同的数据映射到了哈希表中的同一个位置。这种情况会导致哈希表的性能下降,因为哈希表需要在同一个位置上存储多个数据

一、链地址法:
当哈希冲突发生时,创建新单元,并将新单元添加到冲突单元所在链表的尾部。

二、开放寻址法

当哈希冲突发生时,从发生冲突的那个单元起,按照一定的次序,从哈希表中寻找一个空闲的单元,然后把发生冲突的元素存入到该单元。开放寻址法需要的表长度要大于等于所需要存放的元素数量

开放寻址法有多种方式:线性探测法、平方探测法、随机探测法和双重哈希法。这里以线性探测法来帮助读者理解开放寻址法思想

结论:
当数据量明确、装载因子小,适合采用开放寻址法。

5. Go map 的负载因子为什么是6.5

go官方根据: 负载因子,溢出率。平均k v 开销, 查找k 平均个数,查找不存在k 平均个数。 这五个指数来判断的。
主要是为了:
减少哈希冲突:
减少内存浪费
重新哈希成本


详细如下:
loadFactor:负载因子,也有叫装载因子
overflow:溢出率,有溢出 bukcet 的百分比
bytes/entry:平均每对 key/value 的开销字节数
hitprobe:查找一个存在的 key 时,要查找的平均个数
missprobe:查找一个不存在的 key 时,要查找的平均个数

为什么选择 6.5 作为默认负载因子呢?这是一种权衡的结果,考虑了性能和内存的因素
1、减少哈希冲突: 当负载因子过高时,桶的数量相对少,会出现多个键被映射到同一个哈希桶的情况,!导致冲突的概率增加,这会降低访问元素的速度。
2、减少内存浪费: 当负载因子过低时,桶的数量相对多,导致有许多空的或未充分利用的桶,意味着内存利用率不高
3、重新哈希成本: 哈希表的扩容操作会引入一定的成本,因为它涉及到重新计算哈希值、重新分配桶等操作。过于频繁的扩容会影响性能,因此选择一个适度的负载因子可以减少扩容的次数。
6.5 是一个比较理想的值,可以在减少哈希冲突的同时,保证了哈希表的空间利用率

6. Go map 如何扩容

超过负载,map 元素个数>6.5*桶个数
溢出桶太多 2的15次方
当桶·总数<2^15 时,如果溢出桶总数 >= 桶总数,则认为溢出桶过多。
当桶总数 >= 2^15 时,直接与 2^15 比较,当溢出桶总数>=2^15 时,即认为溢出桶太多了。

三、扩容机制
一)双倍扩容
二)等量扩容
三)扩容函数

注意: 由于 map 扩容需要将原有的 key/value 重新搬迁到新的内存地址,如果 map 存储了数以亿计的 key-value,一次性搬迁将会造成比较大的延时,
因此 Go map 的扩容采取了一种称为“渐进式”的方式,原有的 key 并不会一次性搬迁完毕,每次最多只会搬迁2个bucket。

7. Go map 和 sync.Map 谁的性能好,为什么

Go 语言的 sync.Map 支持并发读写,采取了“空间换时间”的机制,冗余了两个数据结构,分别是:read 和 dirty

对比原始 map:
,sync.Map 减少了加锁对性能的影响。它做了一些优化:可以无锁访问read map,而且会优先操作 read map ,倘若只操作 readmap 就可以满足要求,那就不用去操作 write map(dirty),所以在某些特定场景中它发生锁竞争的频率会远远小于 map+RWLock 的实现方式

总结:
优点:适合读多写少的场景
缺点:写多的场景,会导致 read map 缓存失效,需要加锁,冲突变多,性能急剧下降

四:并发

各种并发操作原语对比

[面试口话]二: golang基础

channel 理解

channel管道,高级同步原语,goroutine 之间通信的桥梁使用场景:消息队列、数据传递、信号通知、任务编排、锁
其他锁的在这
xiaobot.net/post/3d67bfcf-e62e-4ac... (可能需要付费查看)这里并不是广告、

数据竞争问题

全是读,没有数据竞争的。
go 命令行有个参数 race 可以帮助检测代码中的数据竞争

检测gc

GODEBUG=’gctrace=1’是一个环境变量设置,用于启用 Go 语言程序中的垃圾回收的跟
踪输出

本作品采用《CC 协议》,转载必须注明作者和本文链接
嗨,我是波波。曾经创业,有收获也有损失。我积累了丰富教学与编程经验,期待和你互动和进步! 公众号:上海PHP自学中心 付费知识星球:破解面试:程序员的求职导师
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
司机 @ 欣昊玉
文章
272
粉丝
335
喜欢
555
收藏
1096
排名:65
访问:12.0 万
私信
所有博文
社区赞助商