【笔记】Go语言的切片

前言

Go语言的切片相当于动态数组,切片存放在内存的堆区

声明切片

  • 没有指定切片长度时,切片容量和切片长度默认都为0,其中没有数据
1
var 切片名 []数据类型

声明时指定切片长度

  • 指定了切片长度时,切片长度为指定值,切片的容量为大于等于指定值的最小偶数,其中数据都为默认值
1
切片名 := make([]数据类型, 切片长度)

定义切片

1
var 切片名 []数据类型 = []数据类型{数据, 数据, ...}

获取切片元素的值

1
切片名[下标]

修改切片元素的值

1
切片名[下标] = 数据

获取切片长度

1
len(切片名)

获取切片容量

  • 容量大于等于长度
  • 自动扩容时
    • 如果没有超过1024字节,每次扩展为上次容量的2倍
    • 如果超过了1024字节,每次扩展为上次容量的1.25倍
1
cap(切片名)

追加切片数据

  • 在切片末尾追加数据,长度将自动扩容
    • 如果扩容后切片长度小于等于4,那么切片的容量为切片的长度
    • 如果扩容后切片长度大于4,那么切片的容量为大于等于切片的长度的最小偶数

因为当声明切片时指定了长度,并且将赋值默认值,所以这里的切片末尾指的指切片最大长度

  • 在每次扩容后,切片在内存中的位置都有可能变化
1
2
切片名 = append(切片名, 数据)
切片名 = append(切片名, 数据, 数据, ...)

遍历切片

1
2
3
4
for i := 0; i < len(切片); i++ {
fmt.Println("切片下标: ", i)
fmt.Println("切片元素: ", 数组名[i])
}
1
2
3
4
for i, v := range 数组名 {
fmt.Println("切片下标: ", i)
fmt.Println("切片元素: ", v)
}

切片的截取

指定区间

  • 包含开始不包含结尾
1
新的切片名 = 旧的切片名[开始位置下标:结束位置下标]

截取到末尾

  • 包含开始位置
1
新的切片名 = 旧的切片名[开始位置下标:]

从头开始截取

  • 不包含结束位置
1
新的切片名 = 旧的切片名[:结束位置下标]

指定截取后的切片容量

  • 新的切片的容量应当大于等于截取后的长度
  • 新的切片的容量应当小于旧的切片的容量
1
新的切片名 = 旧的切片名[开始位置下标:结束位置下标:新的切片的容量]

改变数据

  • 截取后的切片仍然属于旧的切片的一部分,所以当修改新的切片的数据时,旧的切片中数据也会发生改变
1
2
新的切片名[下标] = 新数据
fmt.Println(旧的切片名[下标])

切片数据的拷贝

  • 将旧切片中的数据拷贝到新切片中
  • 切片数据拷贝时,要求新的切片的容量大于等于旧的切片的长度
  • 拷贝操作得到的新切片与旧切片是两个单独的切片,数据不会相互影响
1
2
3
var 旧的切片名 []数据类型 = []数据类型{}
新的切片名 = make([]数据类型, len(旧的切片名))
copy(新的切片, 旧的切片)

只拷贝部分数据

  • 切片数据拷贝时,要求新的切片的容量大于等于产生的新的切片的长度
1
copy(新的切片, 旧的切片[开始位置:结束位置])
1
copy(新的切片, 旧的切片[开始位置:])
1
copy(新的切片, 旧的切片[:结束位置])

切片作为函数参数

  • 切片作为函数参数传递时是地址传递,形参可以改变实参的值
    • 如果是修改切片内数据的操作,实参内的数据会跟随形参发生改变
    • 如果是追加切片数据的操作,实参内的数据有可能不发生改变,因为在追加操作时,内存地址可能发生改变,不变实参指向的内存地址不变,所以实参内的数据可能不会发生改变
1
2
3
4
5
func 函数名(切片名 []数据类型) {}

func main() {
函数名(切片名)
}

切片作为返回值

1
2
3
4
5
6
7
func 函数名(切片名 []数据类型) []数据类型{
return 切片名
}

func main() {
切片名 := 函数名(切片名)
}

完成

参考文献

哔哩哔哩——喔咔咔耶耶