最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

环球头条:Go复合数据类型数组和切片

来源:博客园


(资料图片)

数组

声明&&初始化数组

  • 数组声明需要指定元素及元素个数,语法格式如下
  • 数组用来存储相同唯一类型的,一组已编号且长度固定的序列

var arr_name[num] arr_type

package mainimport "fmt"func main()  {// 写添加元素的个数var test [5]stringfmt.Println(test)for i:=0; i< 4; i++{test[i+1] = "test"}fmt.Println(test)// 不写添加元素的个数, 动态加载列表var arry = [...]int{1, 2, 3, 4, 5, 6}fmt.Println(arry)}/*结果[ test test test test][1 2 3 4 5 6]*/
  • 索引元素[下标]
package mainimport "fmt"func main()  {var test = [...]string{"1","2","3","4"}fmt.Println(test[2])}// 结果 3
  • 索引越界报错invalid argument: index 10 out of bounds
  • 索引越界报错,骗过编译器 panic 用一个变量表示索引
package mainimport "fmt"func main()  {var idx = 10var test = [...]string{"1","2","3","4"}fmt.Println(test[idx])}// 报错 骗过编译器越界

指针数组

  • 数组的元素除了是某个类型外,还可以是某个类型的指针
  • new函数返回一个TYPE类型的数据结构划分内存并执行默认的初始化操作,然后返回这个数据对象的指针
  • 只声明不初始化,必须用new,
  • 两个数组指针直接复制
package mainimport "fmt"func main()  {var arry1 [5] *intfmt.Println(arry1)arry1[0] = new(int)arry1[1] = new(int)arry1[2] = new(int)arry1[3] = new(int)arry1[4] = new(int)*arry1[0] =10*arry1[1] =10*arry1[2] =10*arry1[3] =10*arry1[4] =10fmt.Println(arry1)for i:=0; i < len(arry1); i++{fmt.Printf("%v\n",*arry1[i])fmt.Printf("%v\n",arry1[i])}}// 结果/*[    ][0xc00001e0b0 0xc00001e0b8 0xc00001e0c0 0xc00001e0c8 0xc00001e0d0]1010101010*/
  • 两个数组指针复制
    • 内部存放的是指针,指向同一块地址,直接赋值,内容都一样,看起来是浅拷贝,
    • 但其实是深拷贝
    • 判定依据两个数据指针不同就是深拷贝,指针地址相同就是浅拷贝
package mainimport "fmt"func main()  {var arry1 [3]*stringarry2 := [3]*string{new(string), new(string), new(string)}fmt.Println(arry1)fmt.Println(arry2)arry1 = arry2fmt.Println(arry1)for i:=0; i < len(arry2); i++ {fmt.Printf("%d, %v, %v\n", i, arry1[i], *arry1[i])fmt.Printf("%d, %v, %v\n", i, arry2[i], *arry2[i])}}/*结果[  ][0xc000014260 0xc000014270 0xc000014280][0xc000014260 0xc000014270 0xc000014280]0, 0xc000014260,0, 0xc000014260,1, 0xc000014270,1, 0xc000014270,2, 0xc000014280,2, 0xc000014280,*/

数组指针

  • 数组是一个值类型,所有的值类型变量在赋值和作为参数传递时都将产生一次复制操作
  • 从内存和性能上来看,在函数间船队数组是一个开销很大的操作,因为无论这数组有多厂,都会完整复制,并传递给函数
  • 数组指针只需要很小传递
package mainimport ("fmt""unsafe")func bigArryPoint(arr *[1e6]int64)  {fmt.Printf("[数组指针复制:大小:%d 字节]\n", unsafe.Sizeof(arr))}func bigArry(arr [1e6]int64){fmt.Printf("[数组复制:大小:%d 字节]\n", unsafe.Sizeof(arr))}func main()  {var arry [1e6]int64bigArry(arry)bigArryPoint(&arry)}/*[数组复制:大小:8000000 字节][数组指针复制:大小:8 字节]*/

多维数组

  • 多维数组的典型用例是平面坐标(而为数组)和三维坐标(三维数组)
  • Golang的数组本身只有一个唯独,但是我们可以组合多个数组从而创建出多维数组
package mainimport ("fmt""unsafe")func bigArryPoint(arr *[1e6]int64)  {fmt.Printf("[数组指针复制:大小:%d 字节]\n", unsafe.Sizeof(arr))}func bigArry(arr [1e6]int64){fmt.Printf("[数组复制:大小:%d 字节]\n", unsafe.Sizeof(arr))}func main()  {arry := [4][2] int{{1, 2},{10, 20},{30, 40},{50, 60}}fmt.Println(arry[3])fmt.Println(arry[3][0])}/*结果[50 60]50*/

切片

  • 切片是围绕动态数据来构建的
  • 数组一旦创建就不能更改长度,但是切片可以按需求自动增长和缩小
  • 增长是使用内置的append函数来实现的
  • 缩小通过对切片的再次切片来实现

声明和初始化

var直接声明

package mainimport ("fmt")func main()  {var s1 []intfmt.Println(s1)s1 = append(s1, 1)s1 = append(s1, 1)s1 = append(s1, 1)fmt.Println(s1)var s2 = []int{1,2,3}fmt.Println(s2)}

使用make

  • make([]类型, 长度, 容量)
  • 以类型0值+容量的个数填充slice
package mainimport "fmt"func main()  {// 使用make初始化一个长度为0的slicevar s1 = make([]int, 0)s1 = append(s1, 1)s1 = append(s1, 2)s1 = append(s1, 3)fmt.Println(s1)// 使用make,初始化一个长度为5,容量为5的slicevar s2 = make([]int, 5, 5)s2 = append(s2, 1)s2 = append(s2, 2)s2 = append(s2, 3)fmt.Println(s2)}/*结果[1 2 3][0 0 0 0 0 1 2 3]*/
  • new和make对比
    • 简单说new只分配内存,make用于slice,map,和channel的初始化。
    • 对比表格
函数名适用范围返回值填充值
newnew可以对所有类型进行内存分配new返回指针new填充零值
makemake只能创建类型(slice、map、channel)make返回引用make填充非零值

通过切片创建新的切片

  • 语法如下slice[start:end:cap]
  • 其中start表示从slice的第几个元素开始
  • end控制切片的长度(end-i)
  • cap控制切片的容量,如果没有给定cap,slice的长度值,则表示到底层数组的最尾部
  • 新切片的长度 = end-start
  • 新切片的容量 = cap-start

关键词: 多维数组 添加元素