第21节 go 语言切片原理
❤️💕💕Go语言高级篇章,在此之前建议您先了解基础和进阶篇。Myblog:http://nsddd.top
Go语言基础篇
Go语言100篇进阶
[TOC]
代码~
💡简单的一个案例如下:
// 切片原理
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5, 6}
fmt.Println("s is array:", s)
s1 := s[0:3]
fmt.Println("s1 is slice:", s1)
s2 := s[3:6]
fmt.Println("s2 is slice:", s2)
//s1和s2共享底层数组
_ = append(s1, 7)
fmt.Println("s2 checkout is slice:", s2)
}
提示
按理说,按理说,应该是 append 影响的是 s1 ,与我 s2 有何关系❓
所以打印的是:[4,5,6]
那么你就失望了
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\86-main.go"
s is array: [1 2 3 4 5 6]
s1 is slice: [1 2 3]
s2 is slice: [4 5 6]
s2 checkout is slice: [7 5 6]
原因
则需要我们理解 slice
的底层原理和机制了, slice
说是切片, 但是实际上是一个 映射。
从一个大的 slice
中映射下来,形成一个新的 slice
.
测试
💡简单的一个案例如下:
// Slice principle
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5, 6}
fmt.Println("s is array:", s)
s1 := s[0:3]
fmt.Println("s1 is slice:", s1)
s2 := s[3:6]
fmt.Println("s2 is slice:", s2)
//S1 and s2 share the underlying array
_ = append(s1, 7)
fmt.Println("s1 checkout is slice:", s1)
fmt.Println("s2 checkout is slice:", s2)
//Print s again
fmt.Println("s is array:", s)
//Cut again
s3 := s1[0:2]
fmt.Println("s3 is slice:", s3)
//Add 8 to s3
s3 = append(s3, 8)
fmt.Println("s3 checkout is slice:", s3)
//Print s1
fmt.Println("s1 checkout is slice:", s1)
//Print s2
fmt.Println("s2 checkout is slice:", s2)
//Print s again
fmt.Println("s is array:", s)
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\86-main.go"
s is array: [1 2 3 4 5 6]
s1 is slice: [1 2 3]
s2 is slice: [4 5 6]
s1 checkout is slice: [1 2 3]
s2 checkout is slice: [7 5 6]
s is array: [1 2 3 7 5 6]
s3 is slice: [1 2]
s3 checkout is slice: [1 2 8]
s1 checkout is slice: [1 2 8]
s2 checkout is slice: [7 5 6]
s is array: [1 2 8 7 5 6]
不改变 s2
如果希望不影响 s2
,我们可以使用 s1 = append([]int{}, s1...)
强迫 go 分配新的空间
💡简单的一个案例如下:
// Slice principle
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5, 6}
fmt.Println("s is array:", s)
s1 := s[0:3]
fmt.Println("s1 is slice:", s1)
s2 := s[3:6]
fmt.Println("s2 is slice:", s2)
//S1 and s2 share the underlying array
s1 = append([]int{}, s1...)
fmt.Println("s1 checkout is slice:", s1)
fmt.Println("s2 checkout is slice:", s2)
fmt.Println("s is array:", s)
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\87-main.go"
s is array: [1 2 3 4 5 6]
s1 is slice: [1 2 3]
s2 is slice: [4 5 6]
s1 checkout is slice: [1 2 3]
s2 checkout is slice: [4 5 6]
s is array: [1 2 3 4 5 6]
总结
📜 对上面的解释
我们可以看到有几个很重要的细节,依次展开:
appent
如果不接收那么是临时的,也就是说_ = append(s1, 7)
并不会影响s1
appent
如果接收那么是永久的,也就是说s1 = append(s1, 7)
会影响s1
,还有s2
- 切片是映射 ,
append
本质上是修改和替换 - 如果希望不影响
s2
,我们可以使用s1 = append([]int{}, s1...)
强迫 go 分配新的空间
警告
掌握原理很重要,不要觉得 go 语言简单,简单你咋还在吹水。
kubernetes 源码看了嘛, API Server 的实现了解嘛,docker 的网络实现了解嘛…….