当前位置: 首页 > wzjs >正文

南昌网站建设价格怎么给自己的网站推广

南昌网站建设价格,怎么给自己的网站推广,有关做美食的网站有哪些,建设银行官方网站登录网址1 Slice Slice底层实现原理 切片是基于数组实现的,它的底层是数组,它自己本身非常小,可以理解为对底层数组的抽象。因为基于数组实现,所以它的底层的内存是连续分配的,效率非常高,还可以通过索引获得数据…

1 Slice

Slice底层实现原理

切片是基于数组实现的,它的底层是数组,它自己本身非常小,可以理解为对底层数组的抽象。因为基于数组实现,所以它的底层的内存是连续分配的,效率非常高,还可以通过索引获得数据,可以迭代以及垃圾回收优化。 切片本身并不是动态数组或者数组指针。它内部实现的数据结构通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内。切片本身是一 个只读对象,其工作机制类似数组指针的一种封装。
切片对象非常小,是因为它是只有 3 个字段的数据结构:

  • 指向底层数组的指针
  • 切片的长度
  • 切片的容量

Slice扩容机制

在使用 append 向 slice 追加元素时,若 slice 空间不足则会发生扩容,扩容会重新分配一块更大的内存,将原 slice 拷贝到新 slice ,然后返回新 slice。扩容后再将数据追加进去。
扩容操作只对容量,扩容后的 slice 长度不变,容量变化规则如下:

若 slice 容量小于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一。
若 slice 容量够用,则将新元素追加进去,slice.len++,返回原 slice
若 slice 容量不够用,将 slice 先扩容,扩容得到新 slice,将新元素追加进新 slice,slice.len++,返回新 slice。

Slice与数组区别

array是固定长度的数组,使用前必须确定数组长度,是值类型。
slice是一个引用类型,是一个动态的指向数组切片的指针。
slice是一个不定长的,总是指向底层的数组array的数据结构,可以动态扩容。
创建方式不一样,Slice使用make创建或者根据数组创建。
作为函数参数时,数组传递的是数组的副本,而slice传递的是指针。

2 Map

Map底层实现原理

Golang 中 map 的底层实现是一个散列表,因此实现 map 的过程实际上就是实现散表的过程。在这个散列表中,主要出现的结构体有两个,一个叫 hmap(a header for a go map),一个叫 bmap(a bucket for a Go map,通常叫其 bucket)。
hmap 哈希表
hmap是Go map的底层实现,每个hmap内都含有多个bmap(buckets桶、oldbuckets旧桶、overflow溢出桶),既每个哈希表都由多个桶组成。

  • buckets buckets是一个指针,指向一个bmap数组,存储多个桶。
  • oldbuckets oldbuckets是一个指针,指向一个bmap数组,存储多个旧桶,用于扩容。
  • overflow
    overflow是一个指针,指向一个元素个数为2的数组,数组的类型是一个指针,指向一个slice,slice的元素是桶(bmap)的地址,这些桶都是溢出桶。为什么有两个?因为Go
    map在哈希冲突过多时,会发生扩容操作。[0]表示当前使用的溢出桶集合,[1]是在发生扩容时,保存了旧的溢出桶集合。overflow存在的意义在于防止溢出桶被gc。
  • bmap 哈希桶
    bmap是一个隶属于hmap的结构体,一个桶(bmap)可以存储8个键值对。如果有第9个键值对被分配到该桶,那就需要再创建一个桶,通过overflow指针将两个桶连接起来。在hmap中,多个bmap桶通过overflow指针相连,组成一个链表。

Map进行有序的排序

map每次遍历,都会从一个随机值序号的桶,再从其中随机的cell开始遍历,并且扩容后,原来桶中的key会落到其他桶中,本身就会造成失序
如果想顺序遍历map,先把key放到切片排序,再按照key的顺序遍历map。
或者可以先把map中的key,通过sort包排序,再遍历map。

map 为什么是不安全的

Go map 默认是并发不安全的,同时对 map 进行并发读写的时,程序会 panic,原因如下:Go 官方经过长时间的讨论,认为 map 适配的场景应该是简单的(不需要从多个 gorountine 中进行安全访问的),而不是为了小部分情况(并发访问),导致大部分程序付出锁的代价,因此决定了不支持。
map 在扩缩容时,需要进行数据迁移,迁移的过程并没有采用锁机制防止并发操作,而是会对某个标识位标记为 1,表示此时正在迁移数据。如果有其他 goroutine 对 map 也进行写操作,当它检测到标识位为 1 时,将会直接 panic。
如果想实现map线程安全,有两种方式:
方式一:使用读写锁 map + sync.RWMutex
方式二:使用golang提供的 sync.Map

Map扩容策略

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

超过负载 map元素个数 > 6.5(负载因子) * 桶个数

溢出桶太多

当桶总数<2^15时,如果溢出桶总数>=桶总数,则认为溢出桶过多
当桶总数>215时,如果溢出桶总数>=215,则认为溢出桶过多
扩容机制:

双倍扩容:针对条件1,新建一个buckets数组,新的buckets大小是原来的2倍,然后旧buckets数据搬迁到新的buckets。

等量扩容:针对条件2,并不扩大容量,buckets数量维持不变,重新做一遍类似双倍扩容的搬迁动作,把松散的键值对重新排列一次,使得同一个 bucket 中的 key 排列地更紧密,节省空间,提高 bucket 利用率,进而保证更快的存取。

渐进式扩容:
插入修改删除key的时候,都会尝试进行搬迁桶的工作,每次都会检查oldbucket是否nil,如果不是nil则每次搬迁2个桶,蚂蚁搬家一样渐进式扩容

Map和Slice区别

数组:数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。声明方式:var a [3]int
slice(切片):Slice(切片)代表变长的序列,序列中每个元素都有相同的类型,slice的语法和数组很像,只是没有固定长度而已。
map:在Go语言中,一个map就是一个哈希表的引用,是一个无序的key/value对的集合

Map总结

map是引用类型
map遍历是无序的
map是非线程安全的
map的哈希冲突解决方式是链表法
map的扩容不是一定会新增空间,也有可能是只是做了内存整理
map的迁移是逐步进行的,在每次赋值时,会做至少一次迁移工作
map中删除key,有可能导致出现很多空的kv,这会导致迁移操作,如果可以避免,尽量避免

http://www.dtcms.com/wzjs/802764.html

相关文章:

  • 做花馍网站app营销的核心是什么
  • 招聘公司怎么做网站手机如何创网站
  • 无锡做网站公司多少钱石家庄php网站建设
  • 广东网站设计费用深圳制作网站主页
  • 长沙网络建设的网站商标怎么设计才好看
  • 鄂尔多斯做网站的公司oppo手机应用商店
  • 网站优化是往新闻中心发新闻吗广州站在哪个区
  • 免费在线观看电影电视剧网站规划网站需要几个步骤
  • 新农村建设在哪个网站查食品网站建设 网站定制开发
  • 大同网站建设熊掌号windows网站模板
  • 网站开发设计模板网站建设业务方法
  • 怎样做网站的源代码优秀设计作品的网站
  • 淄博建设网站建设网站要买服务器
  • 旅游宣传网站建设方案高端品牌网站建设兴田德润在那里
  • 南通做百度网站的公司网站需求定制表单
  • 网站推广位怎么设置长春电商网站建设报价
  • 企业网站建设效益分析宣城网站 建设
  • 上海网站建设公司兴田德润简介惠州网吧
  • 关于机关单位网站的建设品牌seo公司
  • 陕西哪些公司做企业网站单位网站建设要多少钱
  • 什么网站可以做miR的差异表达图棋牌软件开发定制软件
  • 钢材贸易网站建设衣服商业网站建设策划书
  • 上海响应式网站wordpress 火车头采集
  • 企业网站是如何做的网上注册公司需要哪些材料和流程
  • 企业产品网站源码甘肃建设厅网站二级建造师报名时间
  • ui界面设计软件湖南网站seo地址
  • 宝安中心网站建设wordpress 同城生活
  • 电脑做视频的网站html制作网站的步骤
  • 模板建站有什么优势网络店铺的营销方法
  • 网站项目名称wordpress前台个人中心插件