GO——数据容器

数据容器

数组与切片

数组和切片有何异同

切片本质上是对数组的封装,他描述一个数组的片段。

数组是一片连续的地址空间,切片是一个结构体,包含长度、容量、底层数组。

// src/runtime/slice.go

type slice struct {
    array unsafe.Pointer //元素指针
    len  int  //  长度
     cap  int // 容量
}

注意:底层数组可以被多个切片同时指向

切片如何被截取

上文说过,底层数组是可以被共用的,

那么 切片被截取的完成后,需要考虑 ——新旧slice 的底层数组是不是共用的。

一般情况下,只有slice 继续append 扩充长度,才会导致底层数组不可用

func main() {
	slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

	s1 := slice[2:5]
	s2 := slice[2:6:7]

	s2 = append(s2, 100)
	s2 = append(s2, 200)

	s1[2] = 20

	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(slice)
}


[2 3 20]
[2 3 4 5 100 200]       
[0 1 2 3 20 5 100 7 8 9]

从上面的例子可以看出,s1 是与slice 公用底层数组,而s2 没有共用,是因为底层数组长度不够,进行了扩充。

切片的容量是怎样增长的

切片容量增长调用的 append 函数

备注: 这里详细去看slice 的文档

切片作为函数参数会被改变吗

前文说到,slice 是作为一个结构体存在的,但是他的数组是以指针的形式。

若直接传slice ,在调用者看来,实参slice 并不会被函数对形参的操作改变,实参是形参的一个复制;

若传的是slice指针,则会影响实参。

但是因为结构体里面是数组以指针的形式存在。

那么在上面不论是直接传slice 还是 slice 指针,都是共用的一个底层数组。!!!

另外提一句: go语言中的函数传参,只有值传递,没有引用传递。

内建函数 make 和new 的区别是什么

首先make 和new 都是用来分配内存的函数。但是适用的类型不同:

make 适用于 slice ,map,channel 等引用函数。

new 适用于 int 型、数组、结构体等值类型。

散列表map

map 的底层实现原理是什么

Go 语言采用的是哈希查找表,并且使用链表法解决哈希冲突

  1. map 内存模型
// src/runtime/map.go

type hmap struct {
    //元素个数 ,调用 len(map) 直接返回值
    count int
    flags uint8
    //buckets 的对数 log_2
    B  uint8
    // overflow 的bucket 近似数
    noverflow uint16
    // 计算key的哈希的时候会传入哈希函数
    hash0 unt32
    // 指向buckets 数组 ,大小为 2^B
    // 如果元素个数为0,就为nil
    buckets unsafe.Pointer
    // 扩容的时候,buckets 长度会是oldbuckets 的两倍
    oldbuckets unsafe.Pointer
    // 指针扩容进度,小于此地址的buckets 完成迁移
    nevacuate uintptr
    extra *mapextra
}

map 中的key 为什么是无序的

随着map 中的key 数量的增多,原有的空间无法保证高效的进行增删改查的操作时就会发生扩容。而map 扩容,会发生key 的搬迁。原来在同一个bucket 中的key ,搬迁后,有些key会发生变动,bucket 序号加上2^B

上面描述了,假定,每次遍历bucket 是依次遍历的。map 是在有增删 的环境下,遍历是无序。

那么为什么真实情况,map 还是无序的?

在Go 的视线中,当遍历map 时,并不是固定从bucket 从0 开始遍历。而是每次都随机一个bucket 开始。

所以 map 是无序的。

float 类型可以作为map 的key 吗

从语法来看,是可以的,Go 语言 只要是可比较类型都可以作为key ,除了 slice ,map,functions 这几种类型,其他类型都可以作为map 的key。 这些类型的共同特征是支持 == 和 != 操作符。如果是结构体,只有hash 后的值和字面值相当,才认同为相同的可以。

如何比较两个map 是否相等

在两个map 深度相等的条件如下:

  1. 都为nil
  2. 非空、长度相等,指向同一个map 实体对象
  3. 响应的key 指向value “深度相等”

三个条件只要满足一条都认为是相等。(直接用== 是错误,相当于 判nil)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值