Datawhale组队学习Task6要求我们巩固学习Go的数组(Array)和切片(Slices),这两个部分真的很重要,需要掌握的知识点很多,我简要的回顾总结一下。

Go数组

An array is a numbered sequence of elements of a single type, called the element type. The number of elements is called the length of the array and is never negative. ----Go官网

初始化数组方式

var  array[5]  int  //方式1
//方式2 定义同时进行初始化
var array[5]int = [5]int{1, 2, 3, 4, 5}
var array = [5]int{1, 2, 3, 4, 5}
var array = [...]int{1, 2, 3, 4, 5}
var array = [...]int{ 1: 12, 0: 15, 4: 45, 2: 41,3:78}
//也可以使用类型推导  
array := [...]string{1: "tom", 2: "jack", 0: "mary"}

数组的遍历

  1. 传统的for循环 for ( i:=0; i< len(array); i++)
  2. for-range结构
// 语法
for index, value := range array { 
      fmt.Println("index = %v, value = %v", index, value) 
}
//如果只关心部分信息可以使用“ _ "来忽略某个数据
// index,value的作用域问题要注意

数组使用注意事项

  • 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化
  • var arr[ ]int 这时arr就是一个slice切片
  • 数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用。
  • 数组创建后,如果没有赋值,有默认值(零值)
  • 数值类型数组:默认值为0 字符串数组:默认值为" " bool数组:默认值为false
  • 使用数组的步骤 1.声明数组并开辟空间 2.给数组各个元素赋值(默认零值) 3.使用数组
  • 数组的下标是从0开始的 数组下标必须在指定范围内使用,否则报panic:数组越界
  • Go的数组属值类型,在默认情况下是值传递,因此会进行值拷贝。数组间不会相互影响。如想在其它函数中,去修改原来的数组,可以使用引用传递(指针方式) (*arr)[ 0 ] =...
  • 长度是数组类型的一部分,在传递函数参数时需要考虑数组的长度,在使用数组作为参数时,必须写成 [length ]int ,如果不写长度那么就是切片了.另外不同的长度的数组也是不一样的。

切片Slices

  • 切片是match数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制。

  • 切片的使用和数组类似,遍历切片、访问切片的元素和求切片长度len(slice)都一样。

  • 切片的长度是可以变化的,因此切片是一个可以动态变化数组。

  • 切片定义的基本语法: var 切片名 [ ]类型 比如:var a[ ] int

  • 可以使用这类的 slice :=a[1:5],代表slice引用了一个数组a,并且引用的数组元素下标是[1:5) 即是不包括下标为5的这个元素

切片在内存中形式

图片来源:https://www.bilibili.com/video/BV1NJ411F7Fv?from=search&seid=4777699173023952698 切片的几个细节

1.对于任何一个切片来说,其都有一个底层数组与之对应,我们可以将切片看作是一个窗口,透过这个窗口可以看到底层数组的一部分元素 2.slice的确是一个引用类型 3.slice从底层来说,其实就是一个数据结构(struct结构体)

切片的使用

  1. 第一种方式:定义一个切片,然后让切片去引用一个已经创建好的数组
var array[3]int = [3]int{1,2,3}
slice := array[1:2]

2.通过make来创建切片. 【基本语法:var 切片名 [ ]type = make( [ ]type, len, [ cap ] )】 参数说明:type:就是数据类型 len:大小 cap:指定切片容量,可选,如果你分配了cap,则要求cap>=len.

var strslice [] string = make([]string,3,5)
strslice[0]=1
strslice[1]=2
strslice[2]=3

3.第3种方式:定义一个切片,直接就指定具体数组,使用原理类似make的方式

var strslice []string = []string{"tom", "jack", "mary"}

方式1和方式2的区别:传统的方式所直接引用的数组对于程序可见,故可以通过数组和切片进行操作;make方式所创建的数组对程序员是不可见的因此只能使用Slice切片进行操作。

切片的遍历

  1. for循环常规方式遍历 使用len(slice)
  2. for-range结构遍历切片
var arr [3]int = [3]int{1,2,3}
slice := arr[1:2]
for index, value := range slice {
    fmt.Println("index=%v, value=%v", index, value)
}

切片的使用注意事项和细节讨论 1.切片初始化时var slice=arr[ startIndex : endIndex ]

  • 说明:从arr数组下标为startIndex,取到下标为endIndex的元素(不含arr[endIndex])。 2.切片初始化时,仍然不能越界。范围在[0-len(arr)]之间,但是可以动态增长.
varslice=arr[0:end]     //可以简写varslice=arr[:end]
varslice=arr[start:len(arr)]   //可以简写:varslice=arr[start:]
varslice=arr[0:len(arr)]       //可以简写:varslice=arr[:]

3.cap是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素。 4.切片定义完后,还不能使用,因为本身是一个空的,需要让其引用到一个数组,或者make一个空间供切片来使用。 5.切片可以继续切片。

var slice1[]int = make([]int, 5, 10)
slice2 := slice1[1:3]
slice2[1] = 100 //这里会同时修改值,因为指向的数据空间是同一个

6.用append内置函数,可以对切片进行动态追加

var slice []int = []int {100,200,300}
slice = append(slice,400,500,600)  //slice=100,200,300,400,500,600

//slice...是固定写法 "..."不可以改变
slice = append(slice,slice...) // slice=100,200,300,400,500,600,100,200,300,400,500,600

切片append操作的本质是对数组扩容Go底层会创建一个新的数组newArray(安装扩容后大小),将slice原来包含的元素拷贝到新的数组newArrayslice重新引用到newArray。 注意:newArray是在底层维护的,程序员不可见。

7.切片的拷贝操作

var slice4 []int = []int{1, 2, 3, 4, 5}
var slice5 = make([]int, 10)
copy(slice5, slice4)
fmt.Println(slice5) //1,2,3,4,5,0,0,0,0,0

1.copy(para1,para2)参数的数据类型是切片 2.按照上面的代码来看,slice4和slice5的数据空间是独立的,互不影响,slice[5] 仍然是1

注意

//下面的代码运行是可以的,虽然slice4的元素多于slice5,但是最终只会保留一个元素
var slice4 = []int{1,2,3,4,5}    
var slice5 = make([]int, 1)    
copy(slice5,slice4)    
fmt.Println(slice5)

8.切片是引用类型,所以在传递时,遵守引用传递机制

string和slice

  • string底层是一个byte数组,因此string也可以进行切片处理
  • string和切片在内存的形式
  • string是不可变的,也就说不能通过str[0]='z'方式来修改字符串
  • 如果需要修改字符串,可以先将string->[]byte/或者[]rune->修改->重写转成string
var str1 string
str1 = "qwertyui"
arr := []byte(str1) //转成[]byte
arr[3] = 'b'        //修改
str2 := string(arr) //重写
fmt.Println(str2)

今日的复习总结就此结束啦,今天不舒服所以晚上想早点休息,就提前写好文章打卡啦