一.数组
- 数组的定义:相同类型的数据集合
- go语言中数组的索引从0开始
- 没有赋值的数值型数组,默认值为0
- 数组一旦被创建,它的大小就是不可改变的
(1)声明数组与打印
- var 变量名 [大小]变量类型
- //数组的声明
- var nums [4]int
- //数组的赋值
- nums[0] = 1
- nums[1] = 2
- nums[2] = 3
- nums[3] = 4
- /***************数组的打印*************/
- fmt.Printf("%T\n", nums) //打印数组的类型:[4]int
- fmt.Println(nums[3]) //打印单个数组的值:4
- fmt.Println("长度:", len(nums)) //打印数组的长度:4
- fmt.Println("容量:", cap(nums)) //打印数组的容量:4
复制代码 (2)数组的初始化
在go语言中,数组有多种初始化方式。
- 常量初始化定义数组
- 快速的定义数组
- 定义不确定长度的数组
- 给指定下标进行赋值操作
- //1、常量的初始化定义数组
- var arrs1 = [5]int{1, 2, 3, 4, 5}
- //2、快速定义数组
- arrs2 := [5]int{6, 7, 8, 9, 10}
- //3、定义不确定长度的数组
- arrs3 := [...]string{"hello", "xuexiangban", "kuangshenshuo"}
- //4、给指定下标进行赋值操作
- arrs4 := [5]int{1: 100, 3: 200}//给下标为1赋值为100,下标为3赋值为200
复制代码 (3)数组的遍历
- //1、for循环遍历数组
- arr1 := [5]int{1, 2, 3, 4, 5} //创建数组
- for i := 0; i < len(arr1); i++ {
- fmt.Println(arr1[i])
- }
- /*输出结果:
- 1
- 2
- 3
- 4
- 5
- */
复制代码- //2、forage循环遍历数组
- for index, value := range arr1 { //index下标,value对应的值
- fmt.Println(index, value)
- }
- /*输出结果:
- 0 1
- 1 2
- 2 3
- 3 4
- 4 5
- */
复制代码 (4)数组是值传递类型
- 在go语言中,数组被看作是值传递类型,因此数组之间可以直接相互赋值
- arr1 := [3]int{1, 2, 3} //创建数组1:整型
- arr2 := [2]string{"hello", "xuexiangban"} //创建数组2:字符型
- arr3 := arr1 //创建数组3直接被赋值数组1
- fmt.Println(arr1, arr3) //打印结果:[1 2 3] [1 2 3]
- arr3 = [3]int{4, 5, 6} //重新赋值
- fmt.Println(arr1, arr3) //[1 2 3] [4 5 6]
复制代码 (5)多维数组
- go语言支持多维数组,以下为常用的多维数组声明方式
- var 变量名[SIZE1][SIZE2]...[SIZEN]变量类型
复制代码- arr := [3][4]int{
- {1, 2, 3, 4},
- {5, 6, 7, 8},
- {9, 10, 11, 12},
- }
复制代码- //forage循环输出
- for _, i := range arr {
- fmt.Println(i) //打印外层
- fmt.Println("=========") //打印内层
- for _, i2 := range i {
- fmt.Println(i2)
- }
- }
- /*打印结果:
- [1 2 3 4]
- =========
- 1
- 2
- 3
- 4
- [5 6 7 8]
- =========
- 5
- 6
- 7
- 8
- [9 10 11 12]
- =========
- 9
- 10
- 11
- 12
- */
复制代码 二.切片
Go语言切片是对数组的抽象
go语言数组的长度是不可改变的,切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大
切片是一种方便、灵活且强大的包装器,切片本身没有任何数据,他们只是对现有数组的引用
切片与数组相比,不需要设定长度,在[]中不用设定值,相对来说比较自由
(1)定义创建切片
切片与数组在定义时不同,可以不用指定长度容量- //1、定义一个切片,里面不添加数据,打印输出
- s1 := []int{}
- fmt.Println(s1) //输出结果:[]
- //2、定义切片向里面添加数据,打印输出类型
- s2 := []int{1, 2, 3}
- fmt.Println(s2) //输出结果:[1 2 3]
- fmt.Printf("%T", s2) //输出结果[]int
复制代码 补充:长度(length)和容量(cap)区别
- 长度(length)指切片中当前包含的元素个数。使用内置函数len()可以获取切片的长度。
- 容量(capacity)指分配给切片的底层数组中可用于存储元素的空间大小。容量至少等于切片长度,但可能会更大以容纳未来的增长。使用内置函数cap()可以获取切片的容量。
- 在创建切片的时候,可以只指定长度也可以同时指定长度和容量。当只指定长度时,切片的容量与长度相等。当同时指定长度和容量时,切片的容量可以大于长度。
(2)make函数创建切片
make函数创建切片,可以指定切片的长度和容量- make([]T,length,capactity) //类型,长度,容量
复制代码- //1、通过make函数来创建切片
- s1 := make([]int, 5, 10) //长度:5,容量为10
- //2、给切片里面的元素进行赋值
- s1[0] = 100
- //3、打印输出长度,容量
- fmt.Println(s1)
- fmt.Println("长度:", len(s1))
- fmt.Println("容量:", cap(s1))
复制代码 (3)切片扩容append
- 注意:追加数据超过容量后,容量只会2倍扩容,地址会发生改变
- //1、创建一个切片s1
- s1 := make([]int, 2, 4)
- fmt.Println("追加数据前的长度和容量:", len(s1), cap(s1))
- //2、s1通过append追加数据
- s1 = append(s1, 1, 2, 3, 4) //追加数据,不是添加数据
- fmt.Println(s1)
- fmt.Println("追加数据后的长度和容量:", len(s1), cap(s1))
- // 3、创建一个s2,将s2中数据追加到s1
- s2 := make([]int, 3, 3)
- s2 = []int{1, 2, 3}
- s1 = append(s1, s2...) //将s2里面的数据追加到s1
- fmt.Println(s1)
复制代码 (4)在已有数组上创建切片
从已有的数组上,直接创建切片,该切片的底层数组就是当前的数组,长度是从start到end切到的数据量,但是容量从start到数组的末尾。
从数组上创建的切片,地址与数组是一样的,因此修改数组或切片的某个值,对应的数组/切片的值也会改变
slice := arr[start:end]- //定义数组和其切片
- arr := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
- s1 := arr[:5] //切片从1-5 [1 2 3 4 5]
- s2 := arr[4:8] //[5 6 7 8]
- s3 := arr[5:] //[6 7 8 9 10]
- s4 := arr[:] //[1 2 3 4 5 6 7 8 9 10]
- fmt.Println(s1) //[1 2 3 4 5]
- fmt.Println(s2) //[5 6 7 8]
- fmt.Println(s3) //[6 7 8 9 10]
- fmt.Println(s4) //[1 2 3 4 5 6 7 8 9 10]
- //修改数组的某个值
- arr[0] = 100 //将数组元素值进行更换
- fmt.Println(arr) //[100 2 3 4 5 6 7 8 9 10]
- fmt.Println(s1) //[100 2 3 4 5 6 7 8 9 10]
- //修改切片的某个值
- s1[1] = 100
- fmt.Println(arr) //[100 100 3 4 5 6 7 8 9 10]
- fmt.Println(s1) //[100 100 3 4 5]
- //查看数组和对应切片的地址
- fmt.Printf("%p\n", s1) //0xc0000ac0f0
- fmt.Printf("%p\n", &arr) //0xc0000ac0f0
复制代码 (5)切片是引用类型
- 与数组不同,数组是值传递类型,而切片是引用类型
- 数组之间可以直接赋值,改变其中一个数组的值,另一个数组的值不会发生改变
- 切片之间若直接赋值,则改变其中一个切片的值,另一个切片的值同样发生改变
- s1 := []int{1, 2, 3, 4, 5}
- s2 := s1
- s2[0] = 100
- fmt.Println(s1, s2) //切片2里元素发生变化,切片1也会跟随着变化
- fmt.Printf("%p\t%p", s1, s2) //说明切片的copy指向的是地址
复制代码 (6)copy深拷贝与浅拷贝
- 深拷贝:拷贝的是数据本身
- 浅拷贝:拷贝的是数据的地址,会导致多个变量指向同一块内存
- 引用类型的数据,默认都是浅拷贝,如切片,集合
- 可以用copy强制实现深拷贝
实现切片的深拷贝
- //1、通过for循环实现切片的深拷贝
- s1 := []int{1, 2, 3, 4}
- s2 := make([]int, 0, 0)
- for i := 0; i < len(s1); i++ {
- s2 = append(s2, s1[i])
- }
- fmt.Println(s1, s2)
- //2、通过copy操作实现深拷贝
- s3 := []int{5, 6, 7, 8}
- fmt.Println(s1, s3)
- copy(s3, s1) //(接收者,传递者) 将s1 copy 给s3
- fmt.Println(s1, s3)
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |