为什么说在go中能使用切片就不要用数组
个人理解 就是因为 对于go语言来说 go的数组是值传递,这会导致很多场景下 修改数组中的元素变的麻烦,而其他语言大部分数组是引用传递 则不会出现类似问题。 举例说明:
定义一个函数 修改数组中的值
func changeArrayPointer(arr [5]int ){
arr[0]=1001
}
func main() {
arr:=[...]int{1,2,3,4,5}
fmt.Println(arr)
changeArrayPointer(arr)
fmt.Println(arr)
}
可以看出来 这里的数组中的值 是没有变化的,在go的数组中 想要在函数调用中修改数组的值,需要使用指针
func changeArrayPointer(arr *[5]int ){
arr[0]=1001
}
func main() {
arr:=[...]int{1,2,3,4,5}
fmt.Println(arr)
changeArrayPointer(&arr)
fmt.Println(arr)
}
显然这不符合其他语言的使用习惯。 而使用切片则可以完全避免这种奇怪的写法
func changeArrayPointer(arr []int ){
arr[0]=1001
}
func main() {
arr:=[]int{1,2,3,4,5}
fmt.Println(arr)
changeArrayPointer(arr)
fmt.Println(arr)
}
可以看出来 ,切片的使用方法是更加适合我们的。
切片本身没有数据,是对数组的一种view,另外一种表现形式而已
func main() {
arr:=[...]int{0,1,2,3,4,5,6}
s:=arr[2:6]
fmt.Println(s)
s[0]=100
fmt.Println(s)
fmt.Println(arr)
}
从上述的执行结果来看,切片修改的值,被如实的反馈到原数组中
切片的length与cap
func main() {
arr:=[...]int{0,1,2,3,4,5,6}
s:=arr[2:6]
fmt.Println(s)
fmt.Println("length:",len(s))
fmt.Println("cap:",cap(s))
}
从上述的执行结果可以明显看出来, 对于一个数组的切片来说,她的len取决于你到底取了多少值,而她的cap的值 则是从你取的第一个数到原数组的结尾
切片不可向前扩展,但是可以向后扩展
func main() {
arr:=[...]int{0,1,2,3,4,5,6}
s:=arr[2:6]
s2:=s[3:5]
fmt.Println(s)
fmt.Println(s2)
}
可以明显看出来 我们的切片s 是2345 不包含原数组6的,这个s的下标索引 也应该是0,1,2,3 到此为止了
但是我们的s2 取的是s的3:5 显然是向后扩展了 但是程序依旧能运行
但是这个向后扩展的特性是不能超过 切片的cap的
s2:=s[3:6]
例如 上述的程序在执行起来 是肯定要报错的
总结如下:
s[i]不可以超越len(s) 向后扩展不可以超越cap(s)
切片的append是值传递,所以必须接受append的返回值
举例:
func printlnSlice(s []int){
fmt.Println("len:", len(s)," cap",cap(s))
}
func main() {
var s []int
println(s)
for i:=0;i<100;i++ {
printlnSlice(s)
s=append(s, 2*i+1)
}
fmt.Println(s)
}
可以看出来 这里cap的扩容是扩容一倍 也要注意切片的扩容一般都是append方法
切片的拷贝与删除
func main() {
var s =[]int{1,2,3,4,5,6}
fmt.Println(s)
printlnSlice(s)
// 切片的拷贝 要设定好长度 否则拷贝会失败
s2:=make([]int, len(s))
copy(s2,s)
fmt.Println(s2)
printlnSlice(s2)
}
切片没有提供删除的方法,只能自己想办法写删除
func main() {
var s =[]int{0,1,2,3,4,5,6}
fmt.Println(s)
//我想删除 下标为3的元素
s1:= append(s[:3],s[4:]...)
fmt.Println(s1)
}
注意下面这个...的写法 这代表把s[4:]这个切片打散 一个个append到后面,否则你这里要写个循环去append 太麻烦了,这个语法 比较奇怪,从其他语言转过来的可能比较容易迷惑,最好记一下