原文参考:https://github.com/golang/go/wiki/SliceTricks
代码示例:
package main
import "fmt"
func initSliceValue(s []int) {
for i := 0; i < len(s); i++ {
s[i] = i
}
}
func main() {
// Append vector
v1 := make([]int, 3)
initSliceValue(v1)
v2 := make([]int, 3)
initSliceValue(v2)
v1 = append(v1, v2...)
fmt.Printf("v1=%v\n", v1)
fmt.Printf("v2=%v\n", v2)
// Copy slice value
a := make([]int, 3)
initSliceValue(a)
b := make([]int, len(a))
copy(b, a)
fmt.Printf("b=%v\n", b)
b1 := append([]int(nil), a...) // 打散方式只是复制,不是原来的值
a[0] = 10
fmt.Printf("b1=%v\n", b1)
// Cut slice
c := make([]int, 10)
initSliceValue(c)
c = append(c[:3], c[5:]...)
fmt.Printf("c=%v, len(c)=%v, cap(c)=%v\n", c, len(c), cap(c))
// Delete index i
d := make([]int, 10)
initSliceValue(d)
i := 5
d = append(d[:i], d[i+1:]...) // 打散追加,O(N)
fmt.Printf("d=%v\n", d)
d1 := make([]int, 10)
d1 = d1[:i+copy(d1[i:], d1[:i+1])] // copy追加,O(N)
fmt.Printf("d1=%v\n", d1)
// Delete without preserving order
e := make([]int, 10)
initSliceValue(e)
e[i] = e[len(e)-1] // O(1)
e = e[:len(e)-1]
// If the type of the element is a pointer or a struct with pointer fields,
// which need to be garbage collected, the above implementations of Cut and
// Delete have a potential memory leak problem: some elements with values are
// still referenced by slice a and thus can not be collected. The following code can fix this problem:
// Cut
i = 3
j := 5
f := make([]*int, 10)
copy(f[i:], f[j:])
for k, n := len(f)-j+i, len(f); k < n; k++ {
f[k] = nil
}
// Delete
g := make([]*int, 10)
if i < len(g) {
copy(g[:i], g[i+1:])
g[i] = nil
}
// Delete without preserving order
h := make([]*int, 10)
h[i] = h[len(h)-1]
h[len(h)-1] = nil
h = h[:len(h)-1]
// Expand elements before x[i]
i = 5
n := 5
x := make([]int, 10)
initSliceValue(x)
x = append(x[:i], append(make([]int, n), x[i:]...)...)
fmt.Printf("x=%v\n", x)
// Extend
y := make([]int, 5)
initSliceValue(y)
y = append(y, make([]int, 5)...)
fmt.Printf("y=%v\n", y)
}
输出结果:
v1=[0 1 2 0 1 2]
v2=[0 1 2]
b=[0 1 2]
b1=[0 1 2]
c=[0 1 2 5 6 7 8 9], len(c)=8, cap(c)=10
d=[0 1 2 3 4 6 7 8 9]
d1=[0 0 0 0 0 0 0 0 0 0]
x=[0 1 2 3 4 0 0 0 0 0 5 6 7 8 9]
y=[0 1 2 3 4 0 0 0 0 0]
第二部分:
package main
import (
"fmt"
"math/rand"
"sort"
)
func initSliceValue(s []int) {
for i := 0; i < len(s); i++ {
s[i] = i
}
}
func isEvenNumber(a int) bool {
return a%2 == 0
}
func main() {
// filter
n := 0
a := make([]int, 10)
initSliceValue(a)
for _, x := range a {
if isEvenNumber(x) {
a[n] = x
n++
}
}
a = a[:n]
fmt.Printf("a=%v\n", a)
// insert element
b := make([]int, 5)
initSliceValue(b)
i := 3
b = append(b[:i], append([]int{-1}, b[i:]...)...)
fmt.Printf("b=%v\n", b)
// push & pop
c := make([]int, 5)
c = append(c, -1)
fmt.Printf("c=%v\n", c)
var x int
x, c = c[len(c)-1], c[:len(c)-1]
fmt.Printf("x=%v, c=%v\n", x, c)
// filter without allocation
d := make([]int, 10)
initSliceValue(d)
e := d[:0]
for _, x := range d {
if isEvenNumber(x) {
e = append(e, x)
}
}
fmt.Printf("d=%v, e=%v\n", d, e)
// alternative choice, if d store pointer
// for i := len(e); i < len(d); i++ {
// d[i] = nil
// }
// reverse slice
f := make([]int, 10)
initSliceValue(f)
for i := len(f)/2 - 1; i >= 0; i-- {
opp := len(a) - 1 - i
a[i], a[opp] = a[opp], a[i]
}
fmt.Printf("f=%v\n", f)
// batching with minimal allocation
actions := make([]int, 10)
initSliceValue(actions)
batchSize := 3
var batches [][]int
for batchSize < len(actions) {
actions, batches = actions[batchSize:], append(batches, actions[0:batchSize:batchSize])
}
batches = append(batches, actions) // append rest elements
fmt.Printf("batches=%v\n", batches)
// In-place deduplicate
in := make([]int, 9)
for i := 0; i < len(in); i++ {
in[i] = rand.Intn(len(in) / 2)
}
sort.Ints(in)
fmt.Println(in)
j := 0
for i := 1; i < len(in); i++ {
if in[i] == in[j] {
continue
}
j++
in[j] = in[i]
}
result := in[:j+1]
fmt.Printf("result=%v\n", result)
}
输出结果:
a=[0 2 4 6 8]
b=[0 1 2 -1 3 4]
c=[0 0 0 0 0 -1]
x=-1, c=[0 0 0 0 0]
d=[0 2 4 6 8 5 6 7 8 9], e=[0 2 4 6 8]
f=[0 1 2 3 4 5 6 7 8 9]
batches=[[0 1 2] [3 4 5] [6 7 8] [9]]
[0 0 1 1 1 2 3 3 3]
result=[0 1 2 3]