golanggolang
append()sliceslicelensliceappendcapsliceslicecap
copy()slicesliceslice

下面是从golang官网源码库中看到的实现代码,如下所示:

  • runtime/slice.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
func slicecopy(to, fm slice, width uintptr) int {
if fm.len == 0 || to.len == 0 {
return 0
}

n := fm.len
if to.len < n {
n = to.len
}

if width == 0 {
return n
}

if raceenabled {
callerpc := getcallerpc(unsafe.Pointer(&to))
pc := funcPC(slicecopy)
racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
}
if msanenabled {
msanwrite(to.array, uintptr(n*int(width)))
msanread(fm.array, uintptr(n*int(width)))
}

size := uintptr(n) * width
if size == 1 { // common case worth about 2x to do here
// TODO: is this still worth it with new memmove impl?
*(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer
} else {
memmove(to.array, fm.array, size)
}
return n
}
slicelenreturn

下面是示例代码,验证一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package main

import (
"regexp"
"log"
"unsafe"
)

func init() {
log.SetFlags(log.Lshortfile|log.LstdFlags)
}

func sliceTest(list []int) {
if len(list) > 0 {
log.Println("func pos 0:", &list[0])
}

log.Println("func pointer:", unsafe.Pointer(&list))
log.Println("------")
}

func copyTest() {
list := make([]int, 0)
log.Println("pointer:", unsafe.Pointer(&list))
sliceTest(list)
log.Println("++++++++++++++")

list = append(list, 1)
log.Println("pos 0:", &list[0])
log.Println("pointer:", unsafe.Pointer(&list))
sliceTest(list)
log.Println("++++++++++++++")

list = append(list, 2)
log.Println("pos 0:", &list[0])
log.Println("pointer:", unsafe.Pointer(&list))
sliceTest(list)
log.Println("++++++++++++++")

copy1 := make([]int, 0)
copy(copy1, list)
log.Println("copy1:", copy1)

copy2 := make([]int, 2)
copy(copy2, list)
log.Println("copy2:", copy2)

copy3 := make([]int, 0, 2)
copy(copy3, list)
log.Println("copy3:", copy3)
log.Println()
}


func main() {
copyTest()
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

pointer: 0xc42000a060
func pointer: 0xc42000a080
------
++++++++++++++
pos 0: 0xc4200160d0
pointer: 0xc42000a060
func pos 0: 0xc4200160d0
func pointer: 0xc42000a0a0
------
++++++++++++++
pos 0: 0xc4200160f0
pointer: 0xc42000a060
func pos 0: 0xc4200160f0
func pointer: 0xc42000a0c0
------
++++++++++++++
copy1: []
copy2: [1 2]
copy3: []
pos 0:slicesliceslicepos 0:func pos 0:
runtime/slice.gomakeslice()slice
1
2
3
4
5
type slice struct {
array unsafe.Pointer
len int
cap int
}
sliceslicearray
runtime/slice.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func growslice(et *_type, old slice, cap int) slice {
// ...

newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
for newcap < cap {
newcap += newcap / 4
}
}
}

// ...
}
slice10241.25

以上golang源码是基于1.9.1版本。