定义
切片是由数组建立的一种方便、灵活且功能强大的包装,切片本身不拥有任何数据。他们只是对现有数组的引用。切片底层以来于数组,是对数组的引用
底层数组如果发生变化,切片也变了;切片发生变化,层数组也变化
切片定义
基于数组生成切片
package main import "fmt" func main() { var a [10]int var s = a[:] fmt.Println(s) } //[0 0 0 0 0 0 0 0 0 0]
注意点
package main import "fmt" func main() { var a [10]int //var s = a[:] // 把数组从第0个位置切到最后一个位置,赋值给s切片 var s []int=a[:] // 中括号中只要不放任何东西就是切片,放了数字就是数组 fmt.Println(s) }
切片定义并初始化
切片只定义不初始化,默认0值为nil
通过make初始化
package main import "fmt" func main() { var s []int=make([]int,3,4) fmt.Println(s) } //[0 0 0]
直接定义并初始化
package main import "fmt" func main() { var s []int=[]int{3,4,5} fmt.Println(s) } //[3 4 5]
切片追加元素
数组不允许追加元素,切片可以
package main import "fmt" func main() { var a [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} var b []int = a[7:8] //b[0]=999 //fmt.Println(a) //[1 2 3 4 5 6 7 999 9 10] //fmt.Println(b) //[999] b = append(b, 888) fmt.Println("切片b:", b) //切片b: [8 888] fmt.Println("数组a:", a) //数组a: [1 2 3 4 5 6 7 8 888 10] fmt.Println(len(b)) //切片长度是2 fmt.Println(cap(b)) //切片容量是3 b = append(b, 777) fmt.Println("切片b:", b) //切片b: [8 888 777] fmt.Println("数组a:", a) //数组a: [1 2 3 4 5 6 7 8 888 777] fmt.Println(len(b)) //切片长度是3 fmt.Println(cap(b)) //切片容量是3 //现在长度是3,容量是3,如果再追加666的话久超过了底层数组大小 //如果超过底层数组大小:1.重新申请一个底层数据,把切片的值copy过去,2.切片的容量变为原来切片容量的两倍,3.现在这个切片跟原来的数组久没有关系了 b=append(b,666) fmt.Println("切片b:",b) //切片b: [8 888 777 666] fmt.Println("数组a:",a) //数组a: [1 2 3 4 5 6 7 8 888 777] fmt.Println(len(b)) //切片长度是4 fmt.Println(cap(b)) //切片长度是6 //修改切片,不会影响最原来的数组 b[0]=9 a[9]=7 fmt.Println("切片b:",b) //切片b: [9 888 777 666] fmt.Println("数组a:",a) //数组a: [1 2 3 4 5 6 7 8 888 7] }
make创建切片
import "fmt" func main() { var s =make([]int,3,4) fmt.Println(s) //[0 0 0] fmt.Println(len(s)) //3 fmt.Println(cap(s)) //4 }
切片的零值
切片的零值为:nil
import "fmt" func main() { var s []int=make([]int,2,2) // 定义,有初始化 fmt.Println(s[0]) //0 if s==nil{ fmt.Println("我是nil") }else { fmt.Println("我不是nil") //我不是nil } }
import "fmt" func main() { var s []int // 只定义,没有初始化 fmt.Println(s) //[] if s==nil{ fmt.Println("我是nil") //我是nil }else { fmt.Println("我不是nil") } }
切片的参数传递
切片是引用类型,当参数传递在函数中修改会影响原来的
go语言的参数传递都是copy传递,因为切片是个引用(地址,指针),把切片复制了一份传入了。
由于切片是引用,在函数中根据引用改了值,改了原来的底层数组,大家都会手影响
package main import "fmt" func main() { var s []int=[]int{3,4,5} testS(s) fmt.Println("调用之后:",s) //调用之后: [999 4 5] } func testS(s []int) { // 在函数中追加切片,一定要注意有没有超过容量,如果超过了容量,超过后再改的值,就不会影响原来的了 fmt.Println(s) //[3 4 5] s[0]=999 //[999 3 5] s=append(s,888,777) //[999 4 5 888 777] s[1]=666 //[999 666 5 888 777] fmt.Println(s) // [999 666 5 888 777] }
package main import "fmt" func main() { var s []int = make([]int, 3, 4) testS(s) fmt.Println("调用之后:", s) //调用之后: [999 0 0] } func testS(s []int) { // 在函数中追加切片,一定要注意有没有超过容量,如果超过了容量,超过后再改的值,就不会影响原来的了 fmt.Println(s) //[0 0 0] s[0] = 999 //[999 0 0] 会影响原来的 s = append(s, 888, 777) //[999 0 0 888 777],追加了超过了底层数组,不依赖于原来的数组了 s[1] = 666 //[999 666 0 888 777] // 不影响原来的数组了 fmt.Println(s) // [999 666 0 888 777] }
copy切片
package main import "fmt" func main() { var a [100000]int var b =a[:3] fmt.Println(b) //[0 0 0] b[0]=999 b[2]=222 fmt.Println(b) //[999 0 222] 使用b,虽然只用3个值,但是底层数组很大,内存占用大 //把b这个切片,copy另一个新切片上 var c= make([]int,2,2) // 基于的底层数组,数组大小是3 copy(c,b) fmt.Println(c) //[999 0] }
多维切片
每一层都要初始化
import "fmt" func main() { //var s [][]int=make([][]int,2,2) //var s [][]int //fmt.Println(s[0]) //[] //fmt.Println(s[0][0]) // 报错,第二层没有初始化 // 循环切片 两层for循环,跟数组一样 var s [][]int=[][]int{{2,3},{4,4,4,5},{6,7,8}} fmt.Println(s) //[[2 3] [4 4 4 5] [6 7 8]] fmt.Println(s[0][1]) //3 }