前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数组和切片

数组和切片

作者头像
暮雨
发布2019-08-21 10:18:48
8480
发布2019-08-21 10:18:48
举报
文章被收录于专栏:云端漫步

数组

在上文对基本类型做了介绍,如,现在需要10个int类型的变量,安装上文中介绍,我们可以声明10个变量,那么100个呢,这样是不有些麻烦?这时数组就出现了。可以声明一个长度为10的数组。数组是有长度和类型的集合,具有连续的存储空间

数组的声明

代码语言:javascript
复制
var aa [10]int // 标准声明
  var bb [10]int = [10]int{} //声明并初始化
  var cc = [10]int{1: 3, 5: 6} // 带索引的式初始化
  var mm = [...]int{1, 3, 4, 5} // 类型推断,长度推断
  dd := [10]int{1, 2} //类型推断式声明
  ee := [...]int{1, 2} 

数组的长度

获取数组的长度可以使用内置函数len取得, 声明数组时,数组的长度必须是一个常量,因为在编译完成后,就需要确定在内存中分配多大的空间进行存储。

数组的访问数组是一种高效的数据结构,它之前高效,是因为,数组在内存空间中的存储是连续,知道第一个元素的地址,通过公式可以快速的定位其要访问的存储单元的地址。公式为:索引对应内存地址=首地址+存储单元长度*索引值

通过查看内存的方式验证下这个结论

基于这种的内存结构,使得它的访问效率极高。在语言层面,数组的访问和赋值可以使用 aa[index] // 访问index的数组 aa[index] = 123 // 数组赋值

数组遍历使用go语言提供的for循环进行遍历

代码语言:javascript
复制
aa := [3]int{1,2,3}
for idx, val := range aa {
   fmt.Printf("下标:%d 值:%d\n",idx, val)
}

for i :=0; i< len(aa); i++ {
    fmt.Printf("下标:%d 值:%d\n",i, aa[i])
}

对数组的介绍在此先画个句号。数组是定长的。当需要使用变长的数组,怎么办?

  • 通过指针修改数组的值 上文中使用gdb工具,通过内存地址偏移的方式,查看了数组对应的内存的值,在程序中通过指 针的方式修改数组的值,go语言不能对不同类型的指针进行转化,但提供了一个强大的类型unsafe.Pointer可以基于它来实现,它有四个规则
  1. 任何指针都可以转换为unsafe.Pointer
  2. unsafe.Pointer可以转换为任何指针
  3. uintptr可以转换为unsafe.Pointer
  4. unsafe.Pointer可以转换为uintptr 基于这样的规则,可以实现以下代码,使用unsafe.Pointer和uintptr对指针进行运算
代码语言:javascript
复制
func main() {
  var aa = [3]int{}

  num1 := (*int)(unsafe.Pointer(&aa))
  *num1 = 1

  num2 := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&aa)) + unsafe.Sizeof(int(0))*1))
  *num2 = 10

  num3 := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&aa)) + unsafe.Sizeof(int(0))*2))
  *num3 = 4

  fmt.Println(aa)
}

切片

接着上文中提出的那个问题?怎么实现变长的数组?基于定长的数组,我们通过封装可以定义一个新的数据类型,实现不定长度的数组。这种数据类型被称为切片。

切片的声明切片的声明同数组声明一样,只是少了长度的指定 如:var aa []int 也可以通过类型推断的方式进行声明

初始化切片使用make进行初始化 aa := make([]int, 1,1) 通过字面量的方式初始化 aa := []int{1,2} 通过数组初始化 arr :=[5]int{1,2,3} aa := aa[0:3]

切片的追加切片内部是基于数组存储数据的,但存储的长度等于数组的最大长度时,再添加元素就会触发扩容,这个实现对外暴露出一个append的函数。如下:基于数组初始化的切片扩容 arr := [3]int{1,2,3} s1 := arr[0:2] // len(s1) < cap(s1) 不会发生扩容 s1 = append(s1, 1) // len(s1) = cap(s1) 触发扩容 s1 = append(s1, 1)

扩容机制:容量小于1024时,成倍的扩容,容量超过1024时,增长因子设为1.25,也就是说每次会增加25%的容量 看到很多书和资料都写的容量小于1024时,是二倍的扩容,但通过实验发现该描述并不准确,如:uint, int8切片在在首次扩容是8倍,uint16, int16是四倍的扩容

切片的迭代 切片的遍历和数组一样可以使用for range或for,此处不做展开

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云端漫记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 切片
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档