[面试题~]Golang

3. 数组和切片

3.1 数组和切片的区别

Go语言中数组是固定长度的,不能动态扩容,在编译期就会确定大小。
切片是一种数据结构,包含一个底层数组的指针,当前切片个数 len 以及切片的最大容量 cap, 描述的是一块数组。

3.2 切片的扩容策略

切片的扩容都是调用growslice方法,不同版本,扩容机制也有细微差距。
Go1.17 版本,切片在扩容时会进行内存对齐,这个和内存分配策略相关。进行内存对齐之后,新 slice 的容量是要 大于等于老 slice 容量的 2倍或者1.25倍。
当新切片需要的容量大于两倍扩容的容量,则直接按照新切片需要的容量扩容,当原 slice 容量小于 1024 的时候,新 slice 容量变成原来的 2 倍;原 slice 容量超过 1024,新 slice 容量变成原来的1.25倍。
在1.18时,又改成不和1024比较了,而是和256比较。
简单地说,就是小切片按照2倍扩容,大切片按照1.25倍扩容。
Go官方注释说这么做的目的是能更平滑的过渡。

3.3 Go 中对 nil 的 Slice 和空 Slice 的处理是一致的吗?

首先 Go 的 JSON 标准库对 nil slice 和 空 slice 的处理是不一致。

  • slice := make([]int,0):slice 不为 nil,但是 slice 没有值,slice 的底层的空间是空的。
  • slice := []int{} :slice 的值是 nil,可用于需要返回 slice 的函数,当函数出现异常的时候,保证函数依然会有 nil 的返回值。

4. map

4.1 map 的底层实现

Golang 中 map 的底层实现是一个散列表,因此实现 map 的过程实际上就是实现散表的过程。在这个散列表中,主要出现的结构体有两个,一个叫 hmap(a header for a go map),一个叫 bmap(a bucket for a Go map,通常叫其 bucket)。

4.2 map 如何扩容

扩容其实就是一个预分配内容的过程,在 map 中的表现是 预分配 bucket。

  1. 双倍扩容:扩容采取了一种称为“渐进式”的方式,原有的 key 并不会一 次性搬迁完毕,每次最多只会搬迁 2 个 bucket。
  2. 等量扩容:重新排列,极端情况下,重新排列也解决不了,map 存储就会蜕变成链表,性能大大降低,此时哈希因子 hash0 的设置,可以降低此类极端场景的发生。

4.3 什么时候会发生扩容

触发 map 扩容的时机:在向 map 插入新 key 的时候,会进行条件检测,符合下面这 2 个条件,就会触发扩容:

  1. 装载因子超过阈值
  2. overflow 的 bucket 数量过多

  • 对于条件 1,元素太多,而 bucket 数量太少,很简单:将 B 加 1,bucket 最大数量(2^B)直接变成原来 bucket 数量的 2 倍。于是,就有新老 bucket 了。注意,这时候元素都在老 bucket 里,还没迁移到新的 bucket 来。新 bucket 只是最大数量变为原来最大数量的 2 倍(2^B * 2) 。
  • 对于条件 2,其实元素没那么多,但是 overflow bucket 数特别多,说明很多 bucket 都没装满。解决办法就是开辟一个新 bucket 空间,将老 bucket 中的元素移动到新 bucket,使得同一个 bucket 中的 key 排列地更紧密。这样,原来,在 overflow bucket 中的 key 可以移动到 bucket 中来。结果是节省空间,提高 bucket 利用率,map 的查找和插入效率自然就会提升。

4.4 map 什么时候会发生迁移

map 扩容完毕后,不会马上就进行迁移。而是采取增量扩容的方式,当有访问到具体 bukcet 时,才会逐渐的进行迁移(将 oldbucket 迁移到 bucket)。

4.5 map 查找

Go 语言中 map 采用的是哈希查找表,由一个 key 通过哈希函数得到哈希值,64 位系统中就生成一个 64bit 的哈希值,由这个哈希值将 key 对应存到不同的桶 (bucket)中,当有多个哈希映射到相同的的桶中时,使用链表解决哈希冲突。
细节:key 经过 hash 后共 64 位,根据 hmap 中 B 的值,计算它到底要落在哪个桶时,桶的数量为 2B ,如 B=5,那么用 64 位最后 5 位表示第几号桶,在用hash 值的高 8 位确定在 bucket 中的存储位置,当前 bmap 中的 bucket 未找到,则查询对应的 overflow bucket,对应位置有数据则对比完整的哈希值, 确定是否是要查找的数据。如果当前 map 处于数据搬移状态,则优先从 oldbuckets 查找。

4.6 map 删除

删除的逻辑相对比较简单,核心是找到 key 的具体位置。在 bucket 中挨个 cell 寻找。找到对应位置后,对 key 或者 value 进行“清零”操作,将 count 值减 1,将对应位置的 tophash 值置成 Empty

4.7 为什么遍历map是无序的?

遍历的过程,就是按顺序遍历 bucket,同时按顺序遍历 bucket 中的 key,而每个 key 进入 bucket 之前都先进行了哈希散列,所以没办法保证遍历的有序性。

4.8 如何实现有序遍历map?

可以把 map 的 key 全部拿出来进行排序,然后根据 key 去获取 value 。

4.9 为什么Go map是非线程安全的?

因为hash map 的内存是按照2的倍数开辟的,当前面开辟的内存不够的时候,会新开辟一段内存,将原来内存的数据转移到新的内存块中,这个过程是没有加锁的,如果这个时候同时有个读的线程过来获取这块内存数据,就会出现安全问题。

4.10 线程安全的map如何实现?

避免map并发读写panic的方式之一就是加锁,考虑到读写性能,可以使用读写锁提供性能。

4.11 Go sync.map 和原生 map 谁的性能好,为什么?

在基准测试中,在并发安全的情况下sync.Map会比我们常用的map+读写锁更加的快,快了五倍,这是得以于只读read设计,减低锁的粒度。但是利用读写锁的话,我们存储的不是一个简单数据类型,而是一个指针对象,那么用普通map+读写锁能很好地控制锁的粒度,达到更好的操作。

4.12 为什么 Go map 的负载因子是 6.5?

源码里定义的阈值的 6.5 (loadFactorNum/loadFactorDen),是经过测试后取出的一个比较合理的因子
因为每个 bucket 有 8 个空位,在没有溢出,且所有的桶都装满了的情况下,装载因子算出来的结果是 8。因此当装载因子超过 6.5 时,表明很多 bucket 都快要装满了,查找效率和插入效率都变低了。在这个时候进行扩容是有必要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/331287.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第三十六天 | 435.无重叠区间、763.划分字母区间、56.合并区间

435.无重叠区间 题目链接:435.无重叠区间 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。 文章讲解/视频讲解:https://programmercarl.com/0435.%E6%9…

Java毕业设计-基于jsp+servlet的家用电器购物商城管理系统-第87期

获取源码资料,请移步从戎源码网:从戎源码网_专业的计算机毕业设计网站 项目介绍 基于jspservlet的家用电器购物商城管理系统:前端 jsp、jquery、layui,后端 servlet、jdbc,角色分为管理员、用户;集成商品…

AI制作《流浪地球3》高清宣传片

AI制作《流浪地球3》高清宣传片 星辰大海,再次启航,人类的冒险,永无止境。The vast expanse of stars and oceans, setting sail once again. Human adventure knows no bounds. 当家园变得遥不可及,我们唯有勇往直前。With our …

电脑端网络记事本哪个安全稳定?

随着互联网科技的飞速发展,越来越多的上班族发现在电脑上使用网络记事本的重要性。这种网络记事本不仅便于记录工作内容,而且自动将数据上传到云端进行备份,让用户不再为数据丢失而担忧。让我们来看看上班族使用网络记事本的好处。 在日常工…

阿里云服务器地域如何选择?哪个地域价格优惠一些?

阿里云服务器地域和可用区怎么选择?地域是指云服务器所在物理数据中心的位置,地域选择就近选择,访客距离地域所在城市越近网络延迟越低,速度就越快;可用区是指同一个地域下,网络和电力相互独立的区域&#…

一文了解GeoTrust SSL证书

在当今互联网的高度连接世界中,确保网站安全性至关重要。SSL证书是保护网站和用户数据的关键组成部分。GeoTrust证书在SSL证书市场上享有盛誉,被许多网站所有者和企业所信赖。JoySSL将深入探讨GeoTrust证书的特点,帮助大家了解该品牌并做出更…

Spring中动态注册和销毁对象

1. 使用说明 通常我们项目中想要往spring容器中注入一个bean可以在项目初始化的时候结合Bean注解实现。但是该方法适合项目初始化时候使用,如果后续想要继续注入对象则无可奈何。本文主要描述一种在后续往spring容器注入bean的方法。 2. 实现 2.1 说明 2.1.1 注册…

Page268~270 11.3.4 wxWidgets项目配置

项目w28_gui的项目配置: 一,编译选项, -pipe -mthreads [[if (GetCompilerFactory().GetCompilerVersionString(_T("gcc")) > _T("4.8.0")) print(_T("-Wno-unused-local-typedefs"));]] 1, -pipe&#…

spark dateformat源码排错

背景 有一个任务 yyyy写成了YYYY,导致年份不对触发告警 select from_unixtime(unix_timestamp(),YYYY-MM-dd HH:mm:ss) 第一时间用spark dateformat搜索下看看官网,发现spark 官网也没有描述YYYY的信息 Datetime patterns - Spark 3.5.0 Documentati…

【计算机组成与体系结构Ⅱ】Cache性能分析(实验)

实验6:Cache性能分析 一、实验目的 1:加深对 Cache 的基本概念、基本组织结构以及基本工作原理的理解。 2:掌握 Cache 容量、相联度、块大小对 Cache 性能的影响。 3:掌握降低 Cache 不命中率的各种方法以及这些方法对提高 Ca…

Springboot智慧校园电子班牌统一管理平台源码

借助AIoT智能物联、云计算技术打造智慧绿色校园,助力实现校园教务管理、教师管理、学籍管理、考勤、信息发布、班级文明建设、校园风采、家校互通等场景功能,打造安全、便捷、绿色的智慧校园。 前后端分离架构 1、使用springbootvue2 2、数据库&#xff…

Day31 46全排列 47全排列II 回溯去重tips 51N皇后 37解数独

46 全排列 给定一个 没有重复 数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3]输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 排列问题与组合问题的不同之处就在于,没有startIndex,同时需要设置一个used数组…

剩余电流继电器装在哪里?电工必备知识

可实时监测和显示TN-S、TT系统配电线路的剩余电流; 每只剩余电流监测仪最多可监测16个回路的剩余电流,剩余电流监测范围为1mA-30A; 每路剩余电流监测均可设置报警值,报警值的设置范围为5mA-30A。每路剩余电流监测可设置为超值…

Docker(一)简介和基本概念

一、简介 本章将带领你进入 Docker 的世界。 什么是 Docker? 用它会带来什么样的好处? 好吧,让我们带着问题开始这神奇之旅。 1.什么是 Docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目&…

Joern环境的安装(Windows版)

Joern环境的安装(Windows版) 网上很少有关于Windows下安装Joern的教程,而我最初使用也是装在Ubuntu虚拟机中,这样使用很占内存,影响体验感。在Windows下使用源码安装Joern也是非常简单的过程: 提前需要的本地环境: …

基于YOLOv8深度学习的智能肺炎诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…

图像处理中,采用极线约束准则来约束特征点匹配搜索空间,理论上在极线上进行搜索。这里的极线是什么线,怎么定义的?基本矩阵F和本质矩阵E有什么区别?

问题描述:图像处理中,采用极线约束准则来约束特征点匹配搜索空间,理论上在极线上进行搜索。这里的极线是什么线,怎么定义的?基本矩阵F和本质矩阵E有什么区别? 问题1解答: 极线是通过极线几何学…

多特征变量序列预测-模型代码全家桶

包括代码、文献、文件解读!!! 包括多特征变量序列预处理的代码, 预测效果好!!!性能优越 包括 完整的风速数据集, 以及已经生成制作好的数据集、标签,对应代码均可以运行…

冻结Prompt微调LM: T5 PET (a)

T5 paper: 2019.10 Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer Task: Everything Prompt: 前缀式人工prompt Model: Encoder-Decoder Take Away: 加入前缀Prompt,所有NLP任务都可以转化为文本生成任务 T5论文的初衷如…

力扣刷MySQL-第四弹(详细讲解)

🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:力扣刷题讲解-MySQL 🍹文章作者技术和水平很有限,如果文中出…
最新文章