首页 > 其他分享 >Go语言精进之路读书笔记第14条——了解map实现原理并高效使用

Go语言精进之路读书笔记第14条——了解map实现原理并高效使用

时间:2024-02-07 17:23:04浏览次数:32  
标签:map 读书笔记 hiter 类型 mapiterinit key Go

14.1 什么是map

map对value的类型没有限制,但是对key的类型有严格要求:key的类型应该严格定义了作为“==”和“!=”两个操作符的操作数时的行为,因此func、map、slice、chan不能作为map的key类型。

map类型不支持“零值可用”,未显式赋初值的map类型变量的零值为nil。对处于零值状态的map变量进行写操作将会导致运行时panic,进行读操作会返回 val 类型的零值作为兜底。

在创建map时,尽量使用cap参数

  • 使用复合字面值创建map类型变量
  • 使用make创建map类型变量L:make(map[string]int, cap)

14.2 map的基本操作

  1. 插入数据:m[k1]=v1
  2. 获取数据个数/容量:len, 不支持通过cap获取容量
  3. 查找和数据读取:v, ok := m["key"] //comma ok
  4. 删除数据:delete(map,k), 删除不存在的key不会导致panic,方法直接结束,不会产生显式提示
  5. 遍历数据:for k,v := range m //遍历是随机的

遍历数据为什么是随机的?

map源码中mapiterinit函数,Go语言为了防止依赖map的循环顺序,故意在key的hash值上又加上了一个随机值

// $GOROOT/src/runtime/map.go:685
// mapiterinit initializes the hiter struct used for ranging over maps.
// The hiter struct pointed to by 'it' is allocated on the stack
// by the compilers order pass or on the heap by reflect_mapiterinit.
// Both need to have zeroed hiter since the struct contains pointers.
func mapiterinit(t *maptype, h *hmap, it *hiter) {
    ...
	// decide where to start
	r := uintptr(fastrand())
	if h.B > 31-bucketCntBits {
		r += uintptr(fastrand()) << 31
	}
    ...
}

14.3 map的内部实现

//todo

14.4 尽量使用cap创建map

特点

  • map和切片一样,也是引用类型,作为函数参数不会有很大性能损耗
  • 不要依赖map的元素遍历顺序
  • map不支持并发读写,只支持并发读,如果要并发读写,可以采用sync.Map
  • 由于map可以自动扩容,map中数据元素的value位置可能在这一过程中发生变化,因此Go不允许获取map中value的地址

标签:map,读书笔记,hiter,类型,mapiterinit,key,Go
From: https://www.cnblogs.com/brynchen/p/18011105

相关文章

  • golang类型转换模块之gconv
    gf框架提供了非常强大的类型转换包gconv,可以实现将任何数据类型转换为指定的数据类型,对常用基本数据类型之间的无缝转换,同时也支持任意类型到struct对象的属性赋值。由于gconv模块内部大量使用了断言而非反射(仅struct转换使用到了反射),因此执行的效率非常高。使用方式:import"g......
  • Go语言的For循环:语法全解析
    Go语言,作为一门旨在提供简洁、高效编程体验的编程语言,其循环结构的设计同样体现了这一理念。在Go中,for循环是唯一的循环语句,但它的灵活性足以应对各种迭代需求。本文将详细介绍Go语言中for循环的语法,通过示例展示其在实际编程中的应用。基本语法Go语言的for循环基本语法如下:for初......
  • 详解golang实现一个带时效的环形队列
    1.需求mysql执行时间超过100ms以上打warn日志,但是一分钟以内这种warn日志超过10条就需要告警。所以需求就是获得一分钟以内mysql的warn的个数。2.分析为什么使用环形队列而不使用slice?因为队列长度固定,所以可以一开始就分配好空间,不用自动扩容,环形的目的就是不用改变数组的值,只用移......
  • Go语言的100个错误使用场景(30-40)|数据类型与字符串使用
    目录前言4.控制结构4.1忽视元素在range循环中是拷贝(#30)4.2忽略在range循环中如何评估表达式(#31)4.3忽略在range中使用指针元素的影响(#32)4.4对map遍历的错误假设(#33)4.5忽略break的作用(#34)4.6在循环中使用defer(#35)5.字符串5.1不理解rune的概念(#36)5.2不准确的字......
  • golang定时器之timer+ticker
    转载: https://juejin.cn/post/7327157426298011663 Timer是一个一次性的定时器,用于在未来的某一时刻执行一次操作。基本使用创建Timer定时器的方式有两种:NewTimer(dDuration)*Timer:该函数接受一个time.Duration类型的参数d(时间间隔),表示定时器在过期之前等待的......
  • Go语言精进之路读书笔记第13条——了解切片实现原理并高效使用
    13.1切片究竟是什么Go数组是值语义的,这意味着一个数组变量表示的是整个数组,对于元素类型长度较大或元素个数较多的数组,如果直接以数组类型参数传递到函数中会有不小的性能损耗。这时很多人会使用数组指针来定义函数参数,但在Go语言中,更地道的方式是使用切片。切片之于数组就像......
  • golang之常用标准库汇总
    1.import"runtime/debug"func StackfuncStack()[]byteStack 返回格式化的go程的调用栈踪迹。 对于每一个调用栈,它包括原文件的行信息和PC值;对go函数还会尝试获取调用该函数的函数或方法,及调用所在行的文本。 func PrintStackfuncPrintStack()PrintStack将Stack......
  • pandas.Series.map() 与 pandas.Series.apply() 的区别!
    pandas.Series.map()与pandas.Series.apply()的区别!输出多列要用apply!输入单列输出单列map,apply输出多列输入多列applypandas.Series.map()和pandas.Series.apply()都是Pandas库中的方法,用于对Series中的每个元素进行操作。但是,它们在使用和功能上有一些区别¹²⁴......
  • 盘点Java集合(容器)概览,Collection和Map在开发中谁用的最多?
    写在开头在Java的世界里万物皆对象。但我认为是万物皆数据,世界由各种各样数据构建起来,我们通过程序去实现数据的增删改查、转入转出、加减乘除等等,不同语言的实现方式殊途同归。由此可见,数据对于程序语言的重要性。这段话是在写数据类型那篇博客时说的,当时是为了引入Java中数据......
  • 使用IDEA直接连接数据库报错:Server returns invalid timezone. Go to 'Advanced' tab
    错误详情:使用IDEA直接连接数据库报错:Serverreturnsinvalidtimezone.Goto'Advanced'tabandset'serverTimezone'propertymanually.错误原因:MySQL驱动中默认时区是UTC,与本地时间有时差。解决方案:点开最右侧导航栏Advanced,找到serverTimezone,在value处填写GMT保存再......