1、切片可以修改大小
2、切片的拷贝不是单纯值的拷贝,一个切片指向了一个数组
1234567 | //切片的声明1 //nilvar slice1 []int //切片的声明2var slice2 []int = make([]int,5)var slice3 []int = make([]int,5,7)numbers:= []int{1,2,3,4,5,6,7,8} |
12345678 | numbers:= []int{1,2,3,4,5,6,7,8}//从下标1一直到下标4,但是不包括下标4numbers1 :=numbers[1:4]//从下标0一直到下标3,但是不包括下标3numbers2 :=numbers[:3]//从下标3一直到结束numbers3 :=numbers[3:] |
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 | package mainimport "fmt"//1、切片可以修改大小//2、切片的拷贝不是单纯值的拷贝,一个切片指向了一个数组//切片的声明1var slice1 []int//切片的声明2var slice2 []int = make([]int,5)var slice3 []int = make([]int,5,7)func main(){ slice4 := make([]int,5) slice5 := make([]int,5,7) slice6 := make([]int,0) fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice4),cap(slice4),slice4) fmt.Printf("len=%d,cap=%d,slice=%v",len(slice5),cap(slice5),slice5) if slice4 ==nil{ fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice4),cap(slice4),slice4) } // slice6 := make([]int,0)不为nil if slice6 !=nil{ fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice6),cap(slice6),slice6) } //var slice1 []int为nil if slice1 ==nil{ fmt.Printf("len=%d,cap=%d,slice=%v\n",len(slice1),cap(slice1),slice1) } sliceTest()}//截取func sliceTest(){ numbers:= []int{1,2,3,4,5,6,7,8} printSliceInfo(numbers) numbers1 :=numbers[1:4] printSliceInfo(numbers1) numbers2 :=numbers[:3] printSliceInfo(numbers2) numbers3 :=numbers[3:] printSliceInfo(numbers3)}//打印切片func printSliceInfo(x []int){ fmt.Printf("len=%d,cap=%d,slice=%v\n",len(x),cap(x),x)} |
1234567891011 | // 切片删除// 删除第一个元素numbers = numbers[1:] // 删除最后一个numbers = numbers[:len(numbers)-1]//删除中间一个元素a := int(len(numbers) / 2)numbers = append(numbers[:a], numbers[a+1:]...) |
数组的拷贝是副本拷贝。对于副本的改变不会影响到
切片的拷贝很特殊,切片的副本仍然指向了相同的数组。所以,对于副本的修改会影响到相同的数组。
下面的例子说明
12345678910111213141516171819202122 | package mainimport "fmt"func main() { //数组是值类型 a := [4]int{1, 2, 3, 4} //切片是引用类型 b := []int{100, 200, 300} c := a d := b c[1] = 200 d[0] = 1 fmt.Println("a=", a, "c=", c) //c[1 200 3 4] a[1 2 3 4] fmt.Println("b=", b, "d=", d) //d[1 200 300] b[1 200 300]} |
12345678910111213 | numbers := make([]int, 0, 20)//append一个元素numbers = append(numbers, 0)//append多个元素numbers = append(numbers, 1, 2, 3, 4, 5, 6, 7)//append添加切片s1 := []int{100, 200, 300, 400, 500, 600, 700}numbers = append(numbers, s1...) //[0 1 2 3 4 5 6 7 100 200 300 400 500 600 700] |
毫无疑问,创建新的目标切片就会有新的指向的数组。数组的copy是对于不同的数组的值的拷贝
12345 | //创建目标切片numbers1 := make([]int, len(numbers), cap(numbers)*2)// 将numbers的元素拷贝到numbers1中count := copy(numbers1, numbers) |
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 | package mainimport "fmt"func main() { fmt.Println("1、--------------") //var numbers []int numbers := make([]int, 0, 20) //append一个元素 numbers = append(numbers, 0) printSlice("numbers:", numbers) //[0] //append多个元素 numbers = append(numbers, 1, 2, 3, 4, 5, 6, 7) printSlice("numbers:", numbers) //[0 1 2 3 4 5 6 7] //append添加切片 s1 := []int{100, 200, 300, 400, 500, 600, 700} numbers = append(numbers, s1...) //[0 1 2 3 4 5 6 7 100 200 300 400 500 600 700] printSlice("numbers:", numbers) fmt.Println("2、--------------") // 切片删除 // 删除第一个元素 numbers = numbers[1:] printSlice("numbers:", numbers) //[ 1 2 3 4 5 6 7 100 200 300 400 500 600 700] // 删除最后一个 numbers = numbers[:len(numbers)-1] printSlice("numbers:", numbers) //[ 1 2 3 4 5 6 7 100 200 300 400 500 600] //删除中间一个元素 a := int(len(numbers) / 2) fmt.Println("中间下标:", a) numbers = append(numbers[:a], numbers[a+1:]...) printSlice("numbers:", numbers) //[1 2 3 4 5 6 100 200 300 400 500 600] fmt.Println("3、--------------") //创建目标切片 numbers1 := make([]int, len(numbers), cap(numbers)*2) // 将numbers的元素拷贝到numbers1中 count := copy(numbers1, numbers) fmt.Println("拷贝的个数:", count) printSlice("numbers1:", numbers1) //拷贝的两个切片是否有关联 numbers[0] = 99 numbers1[len(numbers1)-1] = 100 printSlice("numbers", numbers) printSlice("numbers1", numbers1)}func printSlice(name string, x []int) { fmt.Print(name, "\t") fmt.Printf("地址:%p \t len=%d \t cap=%d \t value=%v \n", x, len(x), cap(x), x)} |
理解了下面代码到底输出什么,就理解了切片的原理。
12345678910111213141516 | package mainimport "fmt"func f(s []string, level int) { if level > 5 { return } s = append(s, fmt.Sprint(level)) f(s, level+1) fmt.Println("level:", level, "slice:", s)}func main() { f(nil, 0)} |
输出结果:
123456 | level: 5 slice: [0 1 2 3 4 5]level: 4 slice: [0 1 2 3 4]level: 3 slice: [0 1 2 3]level: 2 slice: [0 1 2]level: 1 slice: [0 1]level: 0 slice: [0] |
参考资料:
https://dave.cheney.net/2018/07/12/slices-from-the-ground-up
本文链接: https://dreamerjonson.com/2018/11/20/golang-13-slice/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。