Go语言基础语法02

68 阅读4分钟

简单记录一下Go的数组和切片(还有很多有关这两种复合类型的细节没讲,这里只是简单说明):

1.数组

数组的类型名是[n]elementType,其中n是数组长度,elementTyp是数组元素类型。一般初始化有下面几种:

a := [5]int{1, 2, 3, 4, 5}     //定义了一个长度为5的int型数组
a := [...]int{1, 2, 3, 4, 5}   //不指定长度,但根据后面的初始化列表数量就可以确定其长度
a := [3]{1:1,2:3}              //指定总长度,并且根据索引值来初始化值a[0,1,3]
a := [...]int{1:1,2:3}    //不指定总长度,根据索引值来初始化,并且根据最后一个值确定数组长度 a := new([10]int) //通过内置函数new函数来创建数组,与上面不同的是该创建方式得到的值是指针

数组创建完之后长度就固定了,不可以再追加元素,数组长度可以使用内置函数len来获取,需要注意的是初始化数组长度必须是常量表达式,下面是错误初始化例子:

length := 5    //这是一个变量
a:=[length]int 

数组还能进行切割,切割数组的格式为arr[startIndex:endIndex],切割区间是左开右闭区间,例如:

var a = [5]int{1, 2, 3, 4, 5} 
fmt.Println(a[0:4])  //[1,2,3,4]
fmt.Println(a[:3])   //[1,2,3]
fmt.Println(a[3:])   //[4,5]

2.切片

切片就是一种变长数组,数据结构中有指向数组的指针,其实是一种引用类型,换句话来说,切片的底层依旧是数组,Go为切片维护以下三个元素:

type slice struct {
   array unsafe.Pointer //指向底层数组的指针
   len int              //切片的元素数量
   cap int              //底层数组的容量
}

切片的初始化有以下几种:

var nums []int // 值
nums := []int{6, 5, 4} // 值
nums := make([]int, 0, 0) // 值
nums := new([]int) // 指针

其中通过内置函数make创建切片可以确定其长度和容量,值得注意的是第一种初始化是被允许的,但以下声明是不被允许的:

a := make([]int)

这提示我们在用内置函数make创建切片时,一定要声明它的长度,容量可选择声明也可以不声明。

插入元素

切片元素的插入也是需要结合appned函数来使用,例如:

nums := make([]int, 0, 0)                //创建一个长度和容量均为0的切片
nums = append(nums, 1, 2, 3, 4, 5, 6, 7) //往目标切片nums添加元素 [1,2,3,4,5,6,7]
fmt.Println(len(nums), cap(nums))        //此时切片长度为7,容量为8 

在尾部插入元素,就是append最原始的方法,当然也可以在头部和中间插入元素,合理使用append函数就可实现

nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
nums = append(nums, 99, 100) 
fmt.Println(nums) // [1 2 3 4 5 6 7 8 9 10 99 100]

删除元素

同样可以使用append函数来对切片里的元素进行删除操作。

nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
nums = nums[n:]
fmt.Println(nums) //n=3 [4 5 6 7 8 9 10]

这里简单说明一下有关切片的拓展表达式,其格式为:

slice[low:high:max]

low和high的含义与上述数组分割一样,而max则是指最大的容量,如下面的例子则是省略了max,s2的容量其实是cap(s1)-low

s1 := []int{1, 2, 3, 4, 5, 6, 7, 8} //cap(s1) = 8
s2 := s1[3:4]                       //[4]
fmt.Println(cap(s2))                //实际容量为cap(s1) - low = 8 - 3 = 5

这样赋值后,s1和s2共享同一个底层数组,在对s2进行读写操作时,也可能会对s1进行修改,例如:

s1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9,10} // cap = 10
s2 := s1[3:4]                              // cap = 10 - 3 = 7
// 添加新元素,由于容量为7.所以没有扩容,直接修改底层数组
s2 = append(s2, 1)
fmt.Println(s2)                           //[4,1]
fmt.Println(s1)                           //[1,2,3,4,1,6,7,8,9,10]

上述问题中本来要修改s2的值,但同时修改了s1的值,此时要想解决这个问题就可以使用拓展表达式,控制s2的最大容量即可:

 s1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9,10} // cap = 10
 s2 := s1[3:4:4]                           // cap = 4 - 3 = 1
 // 容量不足,分配新的底层数组
 s2 = append(s2, 1)
 fmt.Println(s2)                          //[4,1]
 fmt.Println(s1)                          //[1,2,3,4,5,6,7,8,9,10]