AI智能
改变未来

Go基础(数组、切片)


Go基础

数组

定义数组

需要声明其名称、大小和类型

var name[size] type

例如,这里定义了一个类型为int,大小为4的数组,并分别给数组中赋指
如果不赋指的话,int类型默认为0,string类型默认为空串

var arr1 [4] intarr1[0]=1arr1[1]=2arr1[2]=3arr1[3]=4
  • 数组的长度:表示数组容器中实际存储的数据量。
  • 使用len函数可知数组的长度
    len(array)
  • 数组的容量:表示数组容器中能存储的最大数据量
  • 使用cap函数可知数组的容量
    cap(array)

其他创建数组的方式

通过下面这两种方式效果是相同的

var name[size] intvar name = [size] int

还可以直接通过[…]让程序自动取判断数组内元素的个数

name :=[...]type {elements}

数组的地址=数组首个元素的地址
举个栗子

array:=[...]int {1:2,2:3,5:6}fmt.Println(array)fmt.Printf(\"数组的地址为%p\\n\",&array)fmt.Printf(\"数组的首地址为%p\\n\",&array[0])

这种方式是通过索引给数组赋指,在索引为1的地方值为2,索引为2值为3。得到结果如下

[0 2 3 0 0 6]数组的地址为0xc00000a2a0数组的首地址为0xc00000a2a0

遍历数组

  • 首先可以通过最简单的for循环进行遍历
arr:=[4] int{1,2,3,4}for i:=0;i<len(arr);i++{fmt.Println(arr[i])}
  • 其次可以使用range,得到返回一个索引和一个值
for i,value :=range arr {fmt.Printf(\"索引 %d,值:%d\\n\",i, value)
  • 如果只想得到值可以将索引(i)设置为_,就不会返回索引值了
for _,value :=range arr{fmt.Println(value)

数组排序

使用冒泡算法对数组进行排序
冒泡算法:依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面

arr:=[...] int {10,21,14,9,88,99}for i:=0;i<len(arr);i++{for j:=0;j<len(arr)-i-1;j++{if arr[j]>arr[j+1]{temp:=arr[j]arr[j]=arr[j+1]arr[j+1]=temp}

定义二维数组

定义了一个四行三列的二维数组
相当于有三个一维数组,一维数组的长度为4

a1:=[3][4]int {{1,2,3,4},{5,6,7,8},{9,10,11,12}}

遍历二维数组

与遍历一维数组的方式相仿,只是有两个索引

for i:=0;i<len(a1);i++{for j:=0;j<len(a1[i]);j++{fmt.Printf(\"%d \",a1[i][j])}fmt.Println()

切片

切片可以简单理解为对数组的切片,不过数组是定长的,而切片是可以改变、扩容的。

定义切片
var name[]type

或者使用make方式创建

slice:=make([]int,3,20) //类型 长度 容量

切片操作

  1. 每一个切片都引用了一个底层数组
  2. 切片扩容,就是重新指向一个新的底层数组了
  3. 切片本身不存储任何值,修改切片中的值底层数组的值也要改变
a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}s1 := a[0:5]fmt.Printf(\"a的地址是%p\\n\", &a)fmt.Printf(\"s1地址%p\\n\", s1)

s1是对a的切片,s1本身是没有值,只是他指向的是s1这个底层数组。得到结果

a的地址是0xc000010370s1地址0xc000010370

使用append(slice,element)函数可以给切片添加值
因为添加元素需要扩容,所以要重新赋值
添加元素可以是切片,不过需要在切片后加上…

	slice:=make([]int,3,20) //类型 长度 容量fmt.Println(slice)fmt.Printf(\"长度为%d,容量为%d\\n\",len(slice),cap(slice))slice = append(slice,5)//slice 扩容 要赋值fmt.Print(slice)//slice = append(slice,s2)slice = append(slice,s2...)fmt.Println(slice)

得到结果如下

[0 0 0]长度为3,容量为20[0 0 0 5][0 0 0 5 1 2 3 4]

如果append添加超出容量,容量将成倍数扩张

  • 这里s1的容量只有3,再添加两个元素就需要扩容,而容量是成倍扩张的,比如原始s1容量是3,扩张后就变成了6,如果还需要扩张就是12.
s1:=[]int{1,2,3}fmt.Printf(\"s1的大小%d,s1的容量%d\\n\",len(s1),cap(s1))s2:=append(s1,4,5)fmt.Printf(\"s2的大小%d,s2的容量%d\\n\",len(s2),cap(s2))

而扩容后的切片它是指向的另外一个数组
我们对s1,s2地址输出

fmt.Printf(\"s1的地址%p\\n\",&s1)fmt.Printf(\"s2的地址%p\\n\",&s2)

得到

s1的地址0xc0000044a0s2的地址0xc0000044e0

相当于s2指向的数组是先将s1原数据拷贝过来,再往里面添加新的数据。

  • 更改数组,对应位置切片也要更改
  • 更改切片,对应位置数组也要更改
arr:=[...]int{0,1,2,3,4,5,6,7}s1 := arr[2:6]s1[0]=100fmt.Println(s1)fmt.Println(arr)

结果为

[100 3 4 5][0 1 100 3 4 5 6 7]

切片是对数组[2:6]切片,对切片的第一个数据进行修改,而切片的第一个数据对应数组的第三个数据,所以都会进行相应的更改。

  1. 深拷贝:拷贝的是数据本身,数值类型为值,array,int,float默认为深拷贝
  2. 浅拷贝:拷贝的是数据地址,可以使得多个变量指向同一个内存,引用类型,slice,map默认为浅拷贝。
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Go基础(数组、切片)