[面试题~]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.mzph.cn/news/631480.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FineBI实战项目一(25):实战项目一总结

实在项目使用mysql做数仓库的ODS层,这仅仅是带领大家入门,用mysql做数仓存在很多问题。以实战项目一为例: 1 存在的问题 目前调度用的kettle,数据分析,计算都是落表到mysqlmysql表数量庞大,乱&#xff0c…

css基本写法--详解大全

目录 1.行内样式 2.内嵌样式 3.外链样式 4.import 5.注意 加载顺序 1.行内样式 我们要某个 HTML 标签中去书写样式&#xff0c;它需要使用 style 属性来指定。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&g…

【ArcGIS微课1000例】0088:计算城市建筑物朝向(矩形角度)

文章目录 一、实验描述二、实验数据三、角度计算1. 添加字段2. 计算角度四、方向计算一、实验描述 矩形要素具有长轴和短轴,其长轴方向也称为矩形面的主角度,可用于确定面要素的走向趋势。根据该方向参数,可以对具有矩形特征的地理对象进行方向分析,且适用于很多应用场景,…

什么是NodeJS

1、前言 接触 node.js 有好几年了&#xff0c;也开发了好几个项目了&#xff1b;但每次提起 node.js&#xff0c;始终不敢说自己入门了&#xff0c;归其原因&#xff0c;大概就是如下所示 为了进一步加强理解&#xff0c;系统的梳理相关知识以作备忘&#xff0c;本节将从以下…

视频转码实例:把MP4转为MKV视频,一键批量转换的操作方法

在数字媒体时代&#xff0c;视频格式的多样性是不可避免的。经常把MP4格式的视频转换为MKV格式。MKV格式有较高的音频和视频质量&#xff0c;能在其他设备或软件上播放视频。以下是云炫AI智剪如何把MP4视频转为MKV格式的一键批量转换操作方法。 已转码的mkv视频效果缩略图展示…

20240117在本地机器识别OCR法语电影的字幕效果PK

20240117在本地机器识别OCR法语电影的字幕效果PK 2024/1/17 11:18 1959 - Jirai Cracher Sur Vos Tombes [Gast, Vian].avi https://www.pianbar.net//drama/52892.html 1959[我唾弃你的坟墓]Jirai cracher sur vos tombes[BT下载/迅雷下载] magnet:?xturn:btih:7c9c99d9d048…

Elasticsearch各种高级文档操作

本文来记录下Elasticsearch各种文档操作 文章目录 初始化文档数据查询所有文档匹配查询文档关键字精确查询文档多关键字精确查询文档字段匹配查询文档指定查询字段查询文档过滤字段查询文档概述指定想要显示的字段示例指定不想要显示的字段示例 组合查询文档范围查询文档概述使…

智慧营业厅AI智能视频监控预警系统-商超类连锁店监控解决方案---豌豆云

针对银行、政务、保险、通信、汽车、高速等实体营业厅和办事大厅&#xff0c;提供算力算法平台一体化的智慧营业厅解决方案。 基于边缘端强大的算力&#xff0c;搭配根据行业需求定制化的AI视频分析算法&#xff0c;帮助实现营业厅提升数字化管理水平&#xff0c;加强个性化服…

微服务入门 | 项目分割 | 远程调度Feign | 用户中心erueka 和 nacos

认识微服务 微服务架构演变&#xff1a; 单体架构&#xff1a;所有功能集中在一个项目中开发&#xff0c;打成一个包部署 分布式架构&#xff1a;就是各功能模块的代码不在同一个项目中写了&#xff0c;到时候修改其中一个过能的代码&#xff0c;对另一个功能完全没有任何影响…

循环异步调取接口使用数组promiseList保存,Promise.all(promiseList)获取不到数组内容,then()返回空数组

在使用 vue vant2.13.2 技术栈的项目中&#xff0c;因为上传文件的接口是单文件上传&#xff0c;当使用批量上传时&#xff0c;只能循环调取接口&#xff1b;然后有校验内容&#xff1a;需要所有文件上传成功后才能保存&#xff0c;在文件上传不成功时点击保存按钮&#xff0c…

非常有趣的AI应用-用大语言模型来玩星际争霸2(附代码链接)

非常有趣的AI应用-用大语言模型来玩星际争霸2&#xff08;附代码链接&#xff09; 偶然看到的&#xff0c;比较有意思&#xff0c;分享一下&#xff1a; GitHub地址&#xff1a;Large-Language-Models-play-StarCraftII arxiv&#xff1a;Large Language Models Play StarCra…

ChatGPT 报:“Unable to load history…”如何处理?

ChatGPT界面出现&#xff1a;“Unable to load history…” 说明&#xff1a;无法加载历史记录。。。 原因&#xff1a; 一般是代理的问题&#xff0c;网络加载延迟严重&#xff0c;也可能是官方请求过多&#xff0c;造成响应不及时。 解决&#xff1a; 出现这个问题时&#…

新三板操作指南!哪家证券公司开通新三板交易佣金费率最低?

新三板操作指南&#xff1a;掌握规则&#xff0c;赢得先机&#xff01; 随着中国资本市场的蓬勃发展&#xff0c;新三板市场日益成为投资者关注的焦点。然而&#xff0c;对于许多新手投资者来说&#xff0c;新三板市场的交易规则和流程可能较为陌生。本文将为您详细解读新三板…

移动端开发进阶之蓝牙通讯(一)

移动端开发进阶之蓝牙通讯&#xff08;一&#xff09; 移动端进阶之蓝牙通讯需要综合考虑蓝牙版本选择、协议栈使用、服务匹配、设备连接、安全性和硬件支持等方面。 一、蓝牙版本选择 根据实际需求和应用场景选择合适的蓝牙版本&#xff1b; 1.0&#xff0c;1M/s。 2.0EDR…

线程安全的集合类

Java中提供了许多集合类&#xff0c;其中有的是线程安全的&#xff0c;有的是线程不安全的。线程安全的集合类有&#xff1a; 1. Vector&#xff1a;Vector类实现了一个动态数组&#xff0c;与ArrayList相似&#xff0c;但Vector是同步访问的 2. Stack&#xff1a;Stack是Vec…

C++ 数论相关题目(约数)

1、试除法求约数 主要还是可以成对的求约数进行优化&#xff0c;不然会超时。 时间复杂度根号n #include <iostream> #include <vector> #include <algorithm>using namespace std;int n;vector<int> solve(int a) {vector<int> res;for(int i…

leetcode 每日一题 2024年01月18日 拿出最少数目的魔法豆

题目 给定一个 正整数 数组 beans &#xff0c;其中每个整数表示一个袋子里装的魔法豆的数目。 请你从每个袋子中 拿出 一些豆子&#xff08;也可以 不拿出&#xff09;&#xff0c;使得剩下的 非空 袋子中&#xff08;即 至少还有一颗 魔法豆的袋子&#xff09;魔法豆的数目 …

保证Kafka消息有序性

一、Kafka特性 写入同一个partion分区中的数据是一定有顺序的kafka中一个消费者消费一个partion的数据&#xff0c;消费者取出数据时&#xff0c;也是有顺序的 二、保证消息Kafka消息有序性 在生产者端&#xff0c;应保证消息被写入同一分区。可以在构造消息时指定消息的key…

如何将音频转文字?4个方法帮你轻松搞定!

如何将音频转文字&#xff1f;在日常生活中&#xff0c;将音频转换为文字的应用可以带来很多便利。例如&#xff0c;在会议、讲座、课堂等场合&#xff0c;我们可以使用识别软件将语音转换为文字&#xff0c;方便记录和整理。此外&#xff0c;在语言学习、语音翻译等领域&#…

基于springboot+vue的在线拍卖系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…