go语言map是什么 golang map是引用吗

Go语言使用 map 时尽量不要在 big map 中保存指针

不知道你有没有听过这么一句:在使用 map 时尽量不要在 big map 中保存指针。好吧,你现在已经听过了:)为什么呢?原因在于 Go 语言的垃圾回收器会扫描标记 map 中的所有元素,GC 开销相当大,直接GG。

创新互联公司-专业网站定制、快速模板网站建设、高性价比南陵网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式南陵网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖南陵地区。费用合理售后完善,十载实体公司更值得信赖。

这两天在《Mastering Go》中看到 GC 这一章节里面对比 map 和 slice 在垃圾回收中的效率对比,书中只给出结论没有说明理由,这我是不能忍的,于是有了这篇学习笔记。扯那么多,Show Your Code

这是一个简单的测试程序,保存字符串的 map 和 保存整形的 map GC 的效率相差几十倍,是不是有同学会说明明保存的是 string 哪有指针?这个要说到 Go 语言中 string 的底层实现了,源码在 src/runtime/string.go里,可以看到 string 其实包含一个指向数据的指针和一个长度字段。注意这里的是否包含指针,包括底层的实现。

Go 语言的 GC 会递归遍历并标记所有可触达的对象,标记完成之后将所有没有引用的对象进行清理。扫描到指针就会往下接着寻找,一直到结束。

Go 语言中 map 是基于 数组和链表 的数据结构实现的,通过 优化的拉链法 解决哈希冲突,每个 bucket 可以保存 8 对键值,在 8 个键值对数据后面有一个 overflow 指针,因为桶中最多只能装 8 个键值对,如果有多余的键值对落到了当前桶,那么就需要再构建一个桶(称为溢出桶),通过 overflow 指针链接起来。

因为 overflow 指针的缘故,所以无论 map 保存的是什么,GC 的时候就会把所有的 bmap 扫描一遍,带来巨大的 GC 开销。官方 issues 就有关于这个问题的讨论, runtime: Large maps cause significant GC pauses #9477

无脑机翻如下:

如果我们有一个map [k] v,其中k和v都不包含指针,并且我们想提高扫描性能,则可以执行以下操作。

将“ allOverflow [] unsafe.Pointer”添加到 hmap 并将所有溢出存储桶存储在其中。 然后将 bmap 标记为noScan。 这将使扫描非常快,因为我们不会扫描任何用户数据。

实际上,它将有些复杂,因为我们需要从allOverflow中删除旧的溢出桶。 而且它还会增加 hmap 的大小,因此也可能需要重新整理数据。

最终官方在 hmap 中增加了 overflow 相关字段完成了上面的优化,这是具体的 commit 地址。

下面看下具体是如何实现的,源码基于 go1.15,src/cmd/compile/internal/gc/reflect.go 中

通过注释可以看出,如果 map 中保存的键值都不包含指针(通过 Haspointers 判断),就使用一个 uintptr 类型代替 bucket 的指针用于溢出桶 overflow 字段,uintptr 类型在 GO 语言中就是个大小可以保存得下指针的整数,不是指针,就相当于实现了 将 bmap 标记为 noScan, GC 的时候就不会遍历完整个 map 了。随着不断的学习,愈发感慨 GO 语言中很多模块设计得太精妙了。

差不多说清楚了,能力有限,有不对的地方欢迎留言讨论,源码位置还是问的群里大佬 _

Go语言——sync.Map详解

sync.Map是1.9才推荐的并发安全的map,除了互斥量以外,还运用了原子操作,所以在这之前,有必要了解下 Go语言——原子操作

go1.10\src\sync\map.go

entry分为三种情况:

从read中读取key,如果key存在就tryStore。

注意这里开始需要加锁,因为需要操作dirty。

条目在read中,首先取消标记,然后将条目保存到dirty里。(因为标记的数据不在dirty里)

最后原子保存value到条目里面,这里注意read和dirty都有条目。

总结一下Store:

这里可以看到dirty保存了数据的修改,除非可以直接原子更新read,继续保持read clean。

有了之前的经验,可以猜测下load流程:

与猜测的 区别 :

由于数据保存两份,所以删除考虑:

先看第二种情况。加锁直接删除dirty数据。思考下貌似没什么问题,本身就是脏数据。

第一种和第三种情况唯一的区别就是条目是否被标记。标记代表删除,所以直接返回。否则CAS操作置为nil。这里总感觉少点什么,因为条目其实还是存在的,虽然指针nil。

看了一圈貌似没找到标记的逻辑,因为删除只是将他变成nil。

之前以为这个逻辑就是简单的将为标记的条目拷贝给dirty,现在看来大有文章。

p == nil,说明条目已经被delete了,CAS将他置为标记删除。然后这个条目就不会保存在dirty里面。

这里其实就跟miss逻辑串起来了,因为miss达到阈值之后,dirty会全量变成read,也就是说标记删除在这一步最终删除。这个还是很巧妙的。

真正的删除逻辑:

很绕。。。。

Go语言和其他语言的不同之基本语法

Go语言作为出现比较晚的一门编程语言,在其原生支持高并发、云原生等领域的优秀表现,像目前比较流行的容器编排技术Kubernetes、容器技术Docker都是用Go语言写的,像Java等其他面向对象的语言,虽然也能做云原生相关的开发,但是支持的程度远没有Go语言高,凭借其语言特性和简单的编程方式,弥补了其他编程语言一定程度上的不足,一度成为一个热门的编程语言。

最近在学习Go语言,我之前使用过C#、Java等面向对象编程的语言,发现其中有很多的编程方式和其他语言有区别的地方,好记性不如烂笔头,总结一下,和其他语言做个对比。这里只总结差异的地方,具体的语法不做详细的介绍。

种一棵树最好的时间是十年前,其次是现在。

3)变量初始化时候可以和其他语言一样直接在变量后面加等号,等号后面为要初始化的值,也可以使用变量名:=变量值的简单方式

3)变量赋值 Go语言的变量赋值和多数语言一致,但是Go语言提供了多重赋值的功能,比如下面这个交换i、j变量的语句:

在不支持多重赋值的语言中,交换两个变量的值需要引入一个中间变量:

4)匿名变量

在使用其他语言时,有时候要获取一个值,却因为该函数返回多个值而不得不定义很多没有的变量,Go语言可以借助多重返回值和匿名变量来避免这种写法,使代码看起来更优雅。

假如GetName()函数返回3个值,分别是firstName,lastName和nickName

若指向获得nickName,则函数调用可以这样写

这种写法可以让代码更清晰,从而大幅降低沟通的复杂度和维护的难度。

1)基本常量

常量使用关键字const 定义,可以限定常量类型,但不是必须的,如果没有定义常量的类型,是无类型常量

2)预定义常量

Go语言预定义了这些常量 true、false和iota

iota比较特殊,可以被任务是一个可被编译器修改的常量,在每个const关键字出现时被重置为0,然后在下一个const出现之前每出现一个iota,其所代表的数字会自动加1.

3)枚举

1)int 和int32在Go语言中被认为是两种不同类型的类型

2)Go语言定义了两个浮点型float32和float64,其中前者等价于C语言的float类型,后者等价于C语言的double类型

3)go语言支持复数类型

复数实际上是由两个实数(在计算机中使用浮点数表示)构成,一个表示实部(real)、一个表示虚部(imag)。也就是数学上的那个复数

复数的表示

实部与虚部

对于一个复数z=complex(x,y),就可以通过Go语言内置函数real(z)获得该复数的实部,也就是x,通过imag(z)获得该复数的虚部,也就是y

4)数组(值类型,长度在定义后无法再次修改,每次传递都将产生一个副本。)

5)数组切片(slice)

数组切片(slice)弥补了数组的不足,其数据结构可以抽象为以下三个变量:

6)Map 在go语言中Map不需要引入任何库,使用很方便

Go循环语句只支持for关键字,不支持while和do-while

goto语句的语义非常简单,就是跳转到本函数内的某个标签

今天就介绍到这里,以后我会在总结Go语言在其他方面比如并发编程、面向对象、网络编程等方面的不同及使用方法。希望对大家有所帮助。

golang hashmap的使用及实现

由于go语言是一个强类型的语言,因此hashmap也是有类型的,具体体现在key和value都必须指定类型,比如声明一个key为string,value也是string的map,

需要这样做

大部分类型都能做key,某些类型是不能的,共同的特点是: 不能使用== 来比较,包括: slice, map, function

在迭代的过程中是可以对map进行删除和更新操作的,规则如下:

golang的map是hash结构的,意味着平均访问时间是O(1)的。同传统的hashmap一样,由一个个bucket组成:

那我们怎么访问到对应的bucket呢,我们需要得到对应key的hash值

各个参数的意思:

目前采用的是这一行:

| 6.50 | 20.90 | 10.79 | 4.25 | 6.50 |

当前文章:go语言map是什么 golang map是引用吗
文章分享:https://www.cdcxhl.com/article12/ddscigc.html

成都网站建设公司_创新互联,为您提供虚拟主机定制网站微信公众号网站排名网站导航外贸网站建设

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

h5响应式网站建设