GO语言基础--一些重要的数据结构

在此之前,先介绍一下GO语言相比于其他语言的一些优势

  • 语法简单,学习曲线比较容易

  • 编译速度较快,开发效率也比较高

  • go具有方便的内存分配、垃圾回收机制。另外go支持轻量级线程和通信机制,可以轻松实现高性能并发程序

  • go语言的编译器可以将所有依赖项静态联盟街道二进制文件中,程序的部署比较简单

数组与切片

切片与数组

make 与 new 的区别

在go语言中make与new都是用来初始化变量的,make主要用来初始化切片,map,channel,make可以初始化一个变量的属性,以切片为例,make可以为切片的cap,length进行分配内存空间,后续可以直接调用;而new不会,new只会为一个变量申请内存空间,返回一个指向内存空间的指针,不做其他额外的初始化操作。

切片与数组有什么关系?

答:总:切片的底层就是数组、切片就是对数组的封装。从底层角度来说,数组是一段连续的内存空间,而切片除此之外封装了三个字段,分别是pointer:指针指向数组, Len:数组当前所装数据的长度 、cap:数组的容量,因此 数组是值类型而切片则属于引用类型,另外我们在声明时,数组需要提前定义好数组长度,一但定义好,数组的长度就不能改变。而切片不同,切片可以根据添加的数据进行自动扩容。

切片是如何扩容的?谈谈切片的扩容机制

答:总的来说分为三步:

1.首先声明一个更大长度的数组

2.将数据从原来的数组复制到新的数组中

3.将指针指向新的数组,Len、cap字段进行重置。

另外在声明数组时遵循一些原则,主要分为两个阶段,首先是在go语言1.18版本之前的情况。我们假定需要扩容到X,原先数组长度为A

  1. 如果X>=2A,则直接扩容到X
  2. 如果X<2A且X<1024,则扩容到2A
  3. 如果X>1024,则以1.25A进行不断扩容,直到所扩的容刚好容纳X为止

    在1.18版本之后,将判断标准1024改为了256,采用了"以时间换空间"的思想,换了更小的精度,减少了空间的浪费。

    3.如果X>256,就以 (A+3*256)/4 不断扩容,直到刚好满足需要为止

MAP

go语言中map的底层原理

map的底层原理是哈希表。map相比于切片,数组等,主要有两种优势,一是它给我们提供无序的键值对集合来储存数据;二是它可以提供将近以O(1)的时间复杂度来对数据进行读写删操作。如果后续对key进行重命名等操作,系统会对新的key进行判等,因此map中的key的类型不能为如函数,slice,map等不能判等的数据结构,而value可以为任意类型。另外map的底层结构是桶数组,在我们储存数据的时候,系统通过哈希函数将key解析成相应的哈希值,并将哈希值与key-value映射到特定的桶用于储存和后续操作,当我们进行读操作时,系统会分别判断该数据哈希值的高八位与低八位来粗略的估计数据的大概形式与大概位置。另外,当不同的key产生了相同的value,也就是发生了哈希冲突时,go语言一般会采用拉链法来解决哈希冲突,也就是新的key-value会通过指针被添加到该桶对应链表的末尾,另外为了保证map的读写效率,当一个桶的后面追加了一定数量的链表后,会额外引入一个溢出桶来储存多余的数据,如果装载因子超过一定的阈值或者使用了太多 的溢出桶时,map会进行自动扩容。

map是怎么括容的?

map的扩容主要有两种方式:

1.等量扩容:在使用过多的溢出桶时会进行等量扩容,他会申请原来等量的内存空间,将原来的数据重新整理后,转移到新的内存空间中。目的是提高读写效率

2.增量扩容:主要分为两步,第一步是进入扩容状态,申请原来两倍的桶数量,此时两个指针分别指向新桶和旧桶。2.通过哈希函数重新计算数据在新桶的位置,并且采用渐进式迁移方式将数据从旧桶中搬到新桶中。

渐进式迁移主要分为两部分:一是从第一个桶顺序的将数据迁移到新桶中,如果下一个桶的数据被迁移,则跳过;另一方面,当我们操作某一个桶的元素时,会对两个桶进行迁移操作。这样将整个大的迁移操作分配到每次操作数据时进行,减少了成本的消耗

注意:map结构中没有锁机制,并发不安全,并且采用的哈希进行储存数据,读写都是没有顺序的

channel

channel俗称:通道,是go语言所有基础类型中唯一满足并发安全的类型

四大特点

  • 类型安全,确保发送和接收的数据类型一致

  • 具有阻塞性:当发送或接收操作没有被满足时,会阻塞当前协程,直到满足条件为止

  • 具有缓存:可以指定缓存区的大小,当缓存区已满时,写操作会被阻塞;当缓冲区为空时,读操作会被阻塞

  • 关闭性:channel可以使用close函数关闭,关闭后不能进行写操作,但可以进行读操作

读写一个已关闭的channel会发生什么?

有缓冲 channel

  • 写入一个未被初始化的 channel 永远会被阻塞。

  • 读取一个已关闭的有缓冲 channel

    • 会读取已有的值,直到读完。
    • 之后会返回一个零值和一个布尔值 false,表示 channel 已关闭。
  • 写入一个已关闭的有缓冲 channel

    • 会直接报 panic
    • 写入已关闭的 channel 是非法的。

无缓冲 channel

  • 读取一个已关闭的无缓冲 channel

    • 立即返回一个零值和一个布尔值 false,表示 channel 已经关闭了。
  • 写入一个已关闭的无缓冲 channel

    • 会直接报 panic
    • 写入已关闭的 channel 是非法的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值