## slice全解析

2018-08-24 18:02 轩脉刃 阅读(...) 评论(...) 编辑 收藏

# slice全解析

package main

import (
"fmt"
)

func fun1(x int) {
x = x + 1
}

func fun2(x *int) {
*x = *x + 1
}

func fun3(x []int) {
x = append(x, 3)
}

func fun4(x *[]int) {
*x = append(*x, 3)
}

func fun5(x [4]int) {
x[3] = 100
}

func fun6(x *[4]int) {
(*x)[3] = 200
}

// 传值，传指针
func main() {
x1 := 10
fmt.Printf("%+v\n", x1)
fun1(x1)
fmt.Printf("%+v\n\n", x1)

fmt.Printf("%+v\n", x1)
fun2(&x1)
fmt.Printf("%+v\n\n", x1)

var x3 []int
x3 = append(x3, 0, 1, 2)
fmt.Printf("%+v\n", x3)
fun3(x3)
fmt.Printf("%+v\n\n", x3)

fmt.Printf("%+v\n", x3)
fun4(&x3)
fmt.Printf("%+v\n\n", x3)

var x4 [4]int
for i := 0; i < 4; i++ {
x4[i] = i
}
fmt.Printf("%+v\n", x4)
fun5(x4)
fmt.Printf("%+v\n\n", x4)

fmt.Printf("%+v\n", x4)
fun6(&x4)
fmt.Printf("%+v\n\n", x4)
}

10
10

10
11

[0 1 2]
[0 1 2]

[0 1 2]
[0 1 2 3]

[0 1 2 3]
[0 1 2 3]

[0 1 2 3]
[0 1 2 200]

# slice的结构是uintptr+len+cap

var a []int
a = make([]int, 1)
a := []int{1,2}

# slice的append操作是根据cap和len的关系判断是否申请新的空间

a := make([]int, 1, 10)

package main

import "fmt"
import "unsafe"

func main() {
var a []int

a = append(a, 0)
printSlice("a", a)

a = append(a, 1)
printSlice("a", a)

a = append(a, 2, 3, 4)
printSlice("a", a)
}

func printSlice(s string, x []int) {
fmt.Printf("%s len=%d cap=%d ptr=%p %v\n",s, len(x), cap(x), unsafe.Pointer(&x[0]), x)
}

a len=1 cap=2 ptr=0x10414020 [0]
a len=2 cap=2 ptr=0x10414020 [0 1]
a len=5 cap=8 ptr=0x10458020 [0 1 2 3 4]

# 函数参数是slice的时候传递的是“slice结构”的值拷贝

package main

import (
"fmt"
"unsafe"
)

func fun3(x []int) {
fmt.Printf("%p\n", unsafe.Pointer(&x[0]))
x = append(x, 3)
x[2] = 100
fmt.Printf("%p\n", unsafe.Pointer(&x[0]))
}

func main() {

var x3 []int
x3 = append(x3, 0, 1, 2)
fmt.Printf("%+v\n", x3)
fmt.Printf("%p\n", unsafe.Pointer(&x3[0]))
fun3(x3)
fmt.Printf("%p\n", unsafe.Pointer(&x3[0]))
fmt.Printf("%+v\n\n", x3)

}

[0 1 2]
0x10414020
0x10414020
0x10414020
0x10414020
[0 1 100]


package main

import (
"fmt"
"unsafe"
)

func fun3(x []int) {
fmt.Printf("%p\n", unsafe.Pointer(&x[0]))
x = append(x, 3)
x[3] = 100
fmt.Printf("%p\n", unsafe.Pointer(&x[0]))
}

func main() {
var x3 []int
x3 = append(x3, 0, 1, 2)
fmt.Printf("%+v\n", x3)
fmt.Printf("%p\n", unsafe.Pointer(&x3[0]))
fun3(x3)
fmt.Printf("%p\n", unsafe.Pointer(&x3[0]))
fmt.Printf("%+v\n\n", x3)
}

[0 1 2]
0x10414020
0x10414020
0x10414020
0x10414020
[0 1 2]

package main

import (
"fmt"
"unsafe"
)

func fun3(x []int) {
fmt.Printf("%p\n", unsafe.Pointer(&x[0]))
x = append(x, 3, 4)
x[3] = 100
fmt.Printf("%p\n", unsafe.Pointer(&x[0]))
}

func main() {
var x3 []int
x3 = append(x3, 0, 1, 2)
fmt.Printf("%+v\n", x3)
fmt.Printf("%p\n", unsafe.Pointer(&x3[0]))
fun3(x3)
fmt.Printf("%p\n", unsafe.Pointer(&x3[0]))
fmt.Printf("%+v\n\n", x3)
}

[0 1 2]
0x10414020
0x10414020
0x10458000
0x10414020
[0 1 2]

# 总结

• slice的结构是uintptr+len+cap
• slice的append操作是根据cap和len的关系判断是否申请新的空间
• 函数参数是slice的时候传递的是“slice结构”的值拷贝

# 参考

https://halfrost.com/go_slice/