Golang笔记(一):数组与切片

2018-02-03  本文已影响0人  MaxHere

数组

var array1 [3]int // 元素会被自动初始化为0值 => {0, 0, 0}
array2 := [3]int{1} // 位提供初始化的元素被初始化为零值 => {1, 0, 0}
arary3 := [3]int{1, 2: 3} // 指定索引2的元素初始化值为3 => {1, 0, 3}
array4 := [...]int{1, 2, 3} // 不直接指定长度,编译器会根据元素个数给定长度 => {1, 2, 3}
array5 := [...]int{1, 2: 3} // 指定索引 2 的元素初始化值为3,会影响该数组长度 => {1, 0, 3}
type Student struct {
    name string 
    age    int 
}
studentArray := [...]Student {
    {"studentA", 18}, // 省略结构体标签
    {"studentB", 20}
}

切片

切片本身是个只读对象,其工作机制累死数组指针的一种包装。可以基于数组或数组指针创建切片,以开始和结束索引位置确定引用的数组片段。不支持反向索引,世纪范围是一个右半开区间。属性 cap 表示切片所引用数组片段的真是长度,len 用于限定可读的写元素数量。另外,数组必须 addressable,否则会引发错误。
与数组区别:

  1. 切片创建不需要提前声明长度;而数组需要声明,操作数组索引大于该数组长度,会产生越界的异常。
  2. 切片可以通过 make([]int, 3, 5) 方式创建,第一个参数为类型,第二个参数为长度(len),第三个参数为容量(cap)
  3. 切片的长度(len)和 容量(cap)两个属性不一定相等;而数组的两个属性一定相等。切片底层是数组的一部分或者全部, cap 值为从切片引用该底层数组开头部分到该底层数组结尾的长度,而 len 值为该切片引用的底层数组部分的长度。
  4. 切片是引用类型,而数组是值类型。说白了就是切片传递的是引用,只要对任意一个地方修改原切片值也会改变;而数组是值类型,每次传递相当于重新分配内存创建了一个新的数组,各个之间相互独立不影响。
  5. 切片不支持比较操作,即使元素类型支持也不行,仅可以判断您是否是 nil
sliceA := make([]int, 2, 5)  // len = 2 cap = 5 => {0, 0}
sliceB := make([]int2, 2]) // len = 2 cap = 5 => {0, 0}
sliceC := []int{1, 2, 3, 5: 30} // len = 6 cap = 6 => {1, 2, 3, 0, 0, 30}

注意:
下面两种声明方式,前者只是定义了一个 []int 类型变量,并未执行初始化操作;而后者则用初始化表达式完成了全部创建过程。

var sliceA []int // sliceA == nil true
sliceB := []int{} // sliceB == nil false
  1. 很显然,切片只是很小的结构体对象,用来代替数组传参可以避免复制开销
  2. make 函数允许在运行期动态制定数组长度,绕开了数组类型必须使用编译期常量的限制。

然而,并非所有时候都适合使用切片代替数组,因为切片底层数组可能会在堆上分配内存, 而且小数组在栈上拷贝的消耗也未必就比 make 代价大。

slice := make([]int, 0, 5) // {}
sliceA := append(slice, 10) // {10,}
sliceB := append(sliceB, 20, 30) // {10, 20, 30}
sliceC := append(sliceB, 100, 200, 300) // {10, 20, 30, 100, 200, 300} => 超出 cap, 新切片的地址已经变了

注意:

slice := []int{1, 2, 3, 4, 5}
sliceA := slice[:] // {1, 2, 3, 4, 5}
sliceB := slice[1:3] // {2, 3}
n:= copy(sliceA, sliceB) //sliceA:{2 3 3 4 5} sliceB:{3, 3} n: 2

注意

上一篇下一篇

猜你喜欢

热点阅读