Skip to content

Instantly share code, notes, and snippets.

@5idu
Created April 15, 2019 14:40
Show Gist options
  • Save 5idu/5f9b035ec3cd90a22660595988ca97c0 to your computer and use it in GitHub Desktop.
Save 5idu/5f9b035ec3cd90a22660595988ca97c0 to your computer and use it in GitHub Desktop.
切片小知识点
### 切片
```go
slice := []int{1,2,3,4,5}
newSlice := slice[i:j:k]
```
- newSlice长度:j-i
- newSlice容量:k-i
```go
slice := []int{1,2,3,4,5}
newSlice := slice[2:3]
newSlice[0] = 10
newSlice = append(newSlice, 0)
fmt.Println(newSlice, slice)
// Output:
[10 0] [1 2 10 0 5]
```
- 基于数组或切片创建的新切片,当新切片的容量未超过底层数组的容量时,对新切片中的元素改变,会同时改变底层数组元素,也就是说会影响引用底层数组的其他切片
```go
slice := []int{1,2,3,4,5}
newSlice := slice[2:3]
newSlice = append(newSlice, []int{0,0,0,0}...)
fmt.Println(newSlice, slice)
// Output:
[3 0 0 0 0] [1 2 3 4 5]
```
- 基于数组或切片创建的新切片,当新切片的容量超过底层数组的容量时,对新切片中的元素改变,不会改变底层数组元素,也不会影响引用底层数组的其他切片,因为新切片会创建一个新的数组
- append算法:append函数会智能的增长底层数组的容量,当容量小于1000时,会成倍的增长,当超过1000时,增长因子为1.25,也就是说每次会增加25%的容量
```go
slice := []int{1, 2, 3, 4, 5}
for _, v := range slice {
v = 0
fmt.Println(v)
// Output: 0
}
fmt.Println(slice)
// Output:
[1 2 3 4 5]
```
- for range循环中的值,只是原来切片中元素的拷贝,而不是元素的引用,所以对值的修改不能改变原来切片中的元素值
- 可以使用`slice[k] = x`去改变原始切片中元素的值
```go
slice := []int{1, 2, 3, 4, 5}
for i := 0; i < len(slice); i++ {
slice[i] = 0
}
fmt.Println(slice)
// Output:
[0 0 0 0 0]
```
- 可以在循环中改变切片中的值
```go
func main() {
slice := []int{1, 2, 3, 4, 5}
fmt.Printf("%p\n", &slice)
modify(slice)
fmt.Println(slice)
}
func modify(slice []int) {
fmt.Printf("%p\n", &slice)
slice[1] = 10
}
// Output:
0xc00000c060
0xc00000c080
[1 10 3 4 5]
```
- 我们知道切片是3个字段构成的结构类型,所以在函数间以值的方式传递的时候,占用的内存非常小,成本很低。在传递复制切片的时候,其底层数组不会被复制,也不会受影响,复制只是复制的切片本身,不涉及底层数组
- 函数间传递切片使用值传递,当我们修改一个索引的值后,发现原切片的值也被修改了,说明它们共用一个底层数组,在函数间传递切片非常高效,而且不需要传递指针和处理复杂的语法
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment