Go的数组与切片学习笔记 | 青训营笔记

111 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记。

一、数组

1.1、数组定义

数组的定义与创建方式:

/**
    一、数组的创建方式
*/
func Test_07_01(t *testing.T) {
    //1、定义
    var balance [10]float32
    //2、定义长度且进行初始化必须使用=
    var balance1 = [11]float32{100, 20.1}
    //根据元素长度来设置数组大小
    numArr := []int{1, 2, 3, 4, 5}
    numArr2 := [...]int{1, 2, 3, 4, 5}
    //{指定位置: 指定位置值},其他都为0
    numArr3 := [4]int{2: 100}
    //多组指定位置值
    numArr4 := [5]int{1: 100, 2: 300, 4: 500}
    fmt.Println(balance)
    fmt.Println(balance1)
    fmt.Println(numArr)
    fmt.Println(numArr2)
    fmt.Println(numArr3) //[0 0 100 0]
    fmt.Println(numArr4) //[0 0 100 0]
}

image-20220423203100407

1.2、数组的遍历

/**
    二、数组的遍历
 */
func Test_07_02(t *testing.T) {
    //1、数组赋值以及遍历
    var nums [10]int
    for i := 0; i < len(nums); i++ {
        nums[i] = i * 10 + i
        fmt.Print(nums[i], " ")  //0 11 22 33 44 55 66 77 88 99
    }
    fmt.Println()
    //2、数组的长度
    var nums1 = [...]int{1,2,3}
    fmt.Println(len(nums1)) //3//3、for...range遍历
    for i,value := range nums1{
        fmt.Print("[",i,"] = ", value, "  ")  //[0] = 1  [1] = 2  [2] = 3
    }
}

1.3、多维数组

/**
   三、多维数组
*/
func Test_07_03(t *testing.T) {
   //定义二维数组
   var nums = [2][3]int{
      {1,2,3},
      {4,5,6},
   }
   //遍历二维数组
   for i := 0; i < len(nums); i++ {
      for j := 0; j < len(nums[i]); j++ {
         fmt.Print(nums[i][j], " ")
      }
      fmt.Println()
   }
   /**
      1 2 3
      4 5 6
    */
}

1.4、数组是值类型

Go中的数组是值类型,而不是引用类型。这意味着当它们被分配给一个新变量时,将把原始数组的副本分配给新变量。如果对新变量进行了更改,则不会在原始数组中反映。

/**
    四、数组是值类型,赋值给其他是值拷贝,修改赋值的数组,原先不会改变
*/
func Test_07_04(t *testing.T) {
    //测试改变赋值后的数组,原数组是否会改变?不会,因为是值类型
    var nums = [3]int{1,2,3}
    nums1 := nums
    nums1[2] = 666
    fmt.Println("nums:", nums)  //nums: [1 2 3]
    fmt.Println("num1:", nums1) //num1 [1 2 666]//数组的大小不同,表明类型不同。之后切片可以来进行解决这个问题
    var nums2 [5]int
    //nums = nums2   //此时就会报编译错误,大小不同不能进行赋值
}

注意:数组的大小是类型的一部分。因此[5]int和[25]int是不同的类型。因此,数组不能被调整大小。不要担心这个限制,因为切片的存在是为了解决这个问题。


二、切片

2.1、初步使用

package third_ArraryAndSlice
​
import "fmt"
import "testing"/**
    一、切片定义与使用
    切片:数组的抽象(动态数组),Go 数组的长度不可改变,在特定场景中这样的集合就不太适用。
    与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大
    核心:现有数组的引用。
    描述数据类型:slice像一个结构体,包含三个元素
        1、指针,指向数组中slice指定的开始位置
        2、长度,即slice的长度
        3、最大长度,也就是slice开始位置到数组的最后位置的长度
 */
func Test_08_01(t *testing.T) {
    //1、创建切片。长度为5,容量为10的切片
    mslice := make([]int, 5, 10)
    fmt.Println(mslice,",长度为:", len(mslice), ",容量为:", cap(mslice))//[0 0 0 0 0] ,长度为: 5 ,容量为: 10//2、拿到数组指定位置的切片
    mslice2 := [5]int{1,2,3,4,5}
    mslice3 := mslice2[2:4]  //[2,4)区间位置
    mslice4 := mslice2[:3]  //[0,3)区间位置
    fmt.Println(mslice3) //[3 4]
    fmt.Println(mslice4) //[1 2 3]//3、若是对切片修改,其会对原始数组也进行修改
    mslice3[0] = 5
    fmt.Println()
    fmt.Println("切片修改:", mslice3) //切片修改: [5 4]
    fmt.Println("源数组:", mslice2)  //源数组: [1 2 5 4 5]
}

2.2、长度与容量

/**
   二、切片的长度与容量
 */
func Test_08_02(t *testing.T) {
   var nums = make([]int, 3, 5)
   fmt.Printf("len=%d cap=%d slice=%v\n",len(nums),cap(nums) ,nums)  //len=3 cap=5 slice=[0 0 0]
}

2.3、append()与copy()【前者返回对象时深拷贝;后者复制也是深拷贝】

/**
   三、append()和copy()函数
   append():append 向slice里面追加一个或者多个元素,然后返回一个和slice一样类型的slice
      1、append函数会改变slice所引用的数组的内容,从而影响到引用同一数组的其它slice。
      2、当slice中没有剩余空间(即(cap-len) == 0)时,此时将动态分配新的数组空间。返回的slice数组指针将指向这个空间,而原 数组的内容将保持不变;其它引用此数组的slice则不受影响
​
   copy():copy 函数copy从源slice的src中复制元素到目标dst,并且返回复制的元素的个数
*/
func Test_08_03(t *testing.T) {
   //1、append()追加返回的数组与源数组无关!!!相当于来了层【深拷贝】
   var nums []int
   nums1 := append(nums, 0)
   printSlice(nums)   //len=0,cap=0,slice=[]
   printSlice(nums1)  //len=1,cap=1,slice=[0]
   //添加多个元素
   nums1 = append(nums1, 2,3,4)
   printSlice(nums)   //len=0,cap=0,slice=[]
   printSlice(nums1)  //len=4,cap=4,slice=[0 2 3 4]
​
   //创建当前切片的两倍长度、两倍容量。【注意:[]int,[]必须写在前面】
   slices := make([]int, len(nums1), (cap(nums1)) * 2)
   //2、copy()也是相当于深拷贝,复制之后两者无关
   copy(nums1, slices)  //将nums1中的内容拷贝到slices中(新创建的)
   slices[2] = 5
   println(nums1)
   println(slices)
}
​
//定义函数
func printSlice(x []int)  {
   //注意其中有%d,%v,需要使用printf输出
   fmt.Printf("len=%d,cap=%d,slice=%v\n",len(x), cap(x), x)
}