如果我们使用一个指针作为接收者 , 那么就会其作用了,因为指针接收者传递的是一个指向原值指针的副本,指针的副本,指向的还是原来类型的值,所以修改时,同时也会影响原来类型变量的值 。
41.Golang可变参数函数方法的参数,可以是任意多个,这种我们称之为可以变参数,比如我们常用的fmt.Println()这类函数,可以接收一个可变的参数 。可以变参数 , 可以是任意多个 。我们自己也可以定义可以变参数,可变参数的定义,在类型前加上省略号…即可 。
func main() { print("1","2","3")}func print (a ...interface{}){ for _,v:=range a{fmt.Print(v) } fmt.Println()}
例子中我们自己定义了一个接受可变参数的函数,效果和fmt.Println()一样 。可变参数本质上是一个数组,所以我们向使用数组一样使用它,比如例子中的 for range 循环 。
42.Golang Slice的底层实现切片是基于数组实现的,它的底层是数组,它自己本身非常小,可以理解为对底层数组的抽象 。因为基于数组实现,所以它的底层的内存是连续分配的 , 效率非常高 , 还可以通过索引获得数据 , 可以迭代以及垃圾回收优化 。切片本身并不是动态数组或者数组指针 。它内部实现的数据结构通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内 。切片本身是一个只读对象,其工作机制类似数组指针的一种封装 。切片对象非常小,是因为它是只有3个字段的数据结构:
- 指向底层数组的指针
- 切片的长度
- 切片的容量
文章插图
43.Golang Slice的扩容机制,有什么注意点Go 中切片扩容的策略是这样的:
首先判断,如果新申请容量大于 2 倍的旧容量 , 最终容量就是新申请的容量 。否则判断 , 如果旧切片的长度小于 1024 , 则最终容量就是旧容量的两倍 。
否则判断,如果旧切片长度大于等于 1024,则最终容量从旧容量开始循环增加原来的 1/4 , 直到最终容量大于等于新申请的容量 。如果最终容量计算值溢出,则最终容量就是新申请容量 。
- 情况一:原数组还有容量可以扩容(实际容量没有填充完),这种情况下,扩容以后的数组还是指向原来的数组,对一个切片的操作可能影响多个指针指向相同地址的Slice 。
- 情况二:原来数组的容量已经达到了最大值,再想扩容,Go 默认会先开一片内存区域,把原来的值拷贝过来,然后再执行 append() 操作 。这种情况丝毫不影响原数组 。
44.Golang Map底层实现Golang 中 map 的底层实现是一个散列表,因此实现 map 的过程实际上就是实现散表的过程 。在这个散列表中,主要出现的结构体有两个,一个叫hmap(a header for a go map) , 一个叫bmap(a bucket for a Go map,通常叫其bucket) 。
hmap如下所示:
文章插图
图中有很多字段,但是便于理解 map 的架构,你只需要关心的只有一个 , 就是标红的字段:buckets 数组 。Golang 的 map 中用于存储的结构是 bucket数组 。而 bucket(即bmap)的结构是怎样的呢?bucket:
文章插图
相比于 hmap,bucket 的结构显得简单一些,标橙的字段依然是“核心”,我们使用的 map 中的 key 和 value 就存储在这里 。
“高位哈希值”数组记录的是当前 bucket 中 key 相关的”索引”,稍后会详细叙述 。还有一个字段是一个指向扩容后的 bucket 的指针,使得 bucket 会形成一个链表结构 。整体的结构应该是这样的:
文章插图
Golang 把求得的哈希值按照用途一分为二:高位和低位 。低位用于寻找当前 key属于 hmap 中的哪个 bucket , 而高位用于寻找 bucket 中的哪个 key 。需要特别指出的一点是:map中的key/value值都是存到同一个数组中的 。这样做的好处是:在key和value的长度不同的时候,可以消除padding带来的空间浪费 。
文章插图
Map 的扩容:当 Go 的 map 长度增长到大于加载因子所需的 map 长度时,Go 语言就会将产生一个新的 bucket 数组,然后把旧的 bucket 数组移到一个属性字段 oldbucket中 。
推荐阅读
- 怎么看电脑配置高低(100个电脑基础知识)
- 惠普星13air缺点_惠普星13air有哪些问题
- C# 8.0 添加和增强的功能【基础篇】
- 深度剖析Java的volatile实现原理,再也不怕面试官问了
- iptables和firewalld基础
- JavaSPI详解
- Bob 的生存概率问题
- Web自动化---解决登录页面随机验证码问题
- 数据科学学习手札146 geopandas中拓扑非法问题的发现、诊断与修复
- Python 多重继承时metaclass conflict问题解决与原理探究