Go语言 学习笔记---数组与切片

325 阅读3分钟

为什么说在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)

}

image.png

可以看出来 这里的数组中的值 是没有变化的,在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)
}

image.png

显然这不符合其他语言的使用习惯。 而使用切片则可以完全避免这种奇怪的写法

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)
}

image.png

从上述的执行结果来看,切片修改的值,被如实的反馈到原数组中

切片的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))

}

image.png

从上述的执行结果可以明显看出来, 对于一个数组的切片来说,她的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)

}

image.png

可以明显看出来 我们的切片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)

}

image.png

可以看出来 这里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)

}

image.png

切片没有提供删除的方法,只能自己想办法写删除

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)


}

image.png

注意下面这个...的写法 这代表把s[4:]这个切片打散 一个个append到后面,否则你这里要写个循环去append 太麻烦了,这个语法 比较奇怪,从其他语言转过来的可能比较容易迷惑,最好记一下 image.png